summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKatja Marttila <katja.marttila@qt.io>2017-03-02 13:01:20 +0200
committerKatja Marttila <katja.marttila@qt.io>2017-03-16 13:10:30 +0000
commit77ecd7d03aeea3bb7d10ac8ef448920da11ae306 (patch)
tree09e9db05fee7102cfe6dff7c6172e0929a643457
parent2bb4aedd6b16dd581c299f1bfdd4073d5c827e4a (diff)
Add multiscreen-demo sources
Change-Id: I96652b6d05285b751b6d8a99c81102facc2e8adb Reviewed-by: Alistair Adams <alistair.adams@qt.io> Reviewed-by: Risto Avila <risto.avila@qt.io> Reviewed-by: Tuukka Turunen <tuukka.turunen@theqtcompany.com> Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io> Reviewed-by: Samuli Piippo <samuli.piippo@qt.io>
-rw-r--r--.gitignore64
-rw-r--r--.gitmodules3
-rw-r--r--CanController/Button.qml120
-rw-r--r--CanController/ButtonHolder.qml58
-rw-r--r--CanController/CanController.pro39
-rw-r--r--CanController/Car.qml140
-rw-r--r--CanController/CarUI.qml462
-rw-r--r--CanController/CenterViewOff.pngbin0 -> 1794 bytes
-rw-r--r--CanController/CenterViewOffOpt.pngbin0 -> 2008 bytes
-rw-r--r--CanController/CenterViewOn.pngbin0 -> 1799 bytes
-rw-r--r--CanController/CenterViewOnOpt.pngbin0 -> 1728 bytes
-rw-r--r--CanController/E-Car_BackDoorLeftOFF.pngbin0 -> 2003 bytes
-rw-r--r--CanController/E-Car_BackDoorLeftON.pngbin0 -> 2030 bytes
-rw-r--r--CanController/E-Car_BackDoorRightOFF.pngbin0 -> 1986 bytes
-rw-r--r--CanController/E-Car_BackDoorRightON.pngbin0 -> 2006 bytes
-rw-r--r--CanController/E-Car_BrakesOFF.pngbin0 -> 2039 bytes
-rw-r--r--CanController/E-Car_BrakesON.pngbin0 -> 2088 bytes
-rw-r--r--CanController/E-Car_FrontDoorLeftOFF.pngbin0 -> 2166 bytes
-rw-r--r--CanController/E-Car_FrontDoorLeftON.pngbin0 -> 2198 bytes
-rw-r--r--CanController/E-Car_FrontDoorRightOFF.pngbin0 -> 2092 bytes
-rw-r--r--CanController/E-Car_FrontDoorRightON.pngbin0 -> 2127 bytes
-rw-r--r--CanController/E-Car_HoodOFF.pngbin0 -> 2747 bytes
-rw-r--r--CanController/E-Car_HoodON.pngbin0 -> 2811 bytes
-rw-r--r--CanController/E-Car_LowBeamsOFF.pngbin0 -> 2295 bytes
-rw-r--r--CanController/E-Car_LowBeamsON.pngbin0 -> 2284 bytes
-rw-r--r--CanController/E-Car_Shape.pngbin0 -> 5855 bytes
-rw-r--r--CanController/E-Car_TrunkOFF.pngbin0 -> 1957 bytes
-rw-r--r--CanController/E-Car_TrunkON.pngbin0 -> 2002 bytes
-rw-r--r--CanController/E-Car_TurnLeftOFF.pngbin0 -> 2134 bytes
-rw-r--r--CanController/E-Car_TurnLeftON.pngbin0 -> 2189 bytes
-rw-r--r--CanController/E-Car_TurnRightOFF.pngbin0 -> 2083 bytes
-rw-r--r--CanController/E-Car_TurnRightON.pngbin0 -> 2090 bytes
-rw-r--r--CanController/Gear.qml455
-rw-r--r--CanController/GearAutomatic.qml236
-rw-r--r--CanController/Icon_BulbFailure_OFF.pngbin0 -> 1719 bytes
-rw-r--r--CanController/Icon_BulbFailure_ON.pngbin0 -> 1675 bytes
-rw-r--r--CanController/Icon_HazardWarning_OFF.pngbin0 -> 1635 bytes
-rw-r--r--CanController/Icon_HazardWarning_ON.pngbin0 -> 1641 bytes
-rw-r--r--CanController/Icon_LowBeam_OFF.pngbin0 -> 1916 bytes
-rw-r--r--CanController/Icon_LowBeam_ON.pngbin0 -> 1892 bytes
-rw-r--r--CanController/Icon_ParkingBrake_OFF.pngbin0 -> 1192 bytes
-rw-r--r--CanController/Icon_ParkingBrake_ON.pngbin0 -> 1798 bytes
-rw-r--r--CanController/Icon_TurnLeft_OFF.pngbin0 -> 1217 bytes
-rw-r--r--CanController/Icon_TurnLeft_ON.pngbin0 -> 1234 bytes
-rw-r--r--CanController/Icon_TurnRight_OFF.pngbin0 -> 1210 bytes
-rw-r--r--CanController/Icon_TurnRight_ON.pngbin0 -> 1235 bytes
-rw-r--r--CanController/Icon_TyreMalfunction_OFF.pngbin0 -> 1546 bytes
-rw-r--r--CanController/Icon_TyreMalfunction_ON.pngbin0 -> 1532 bytes
-rw-r--r--CanController/S-Car_BrakesOFF.pngbin0 -> 2042 bytes
-rw-r--r--CanController/S-Car_BrakesON.pngbin0 -> 2061 bytes
-rw-r--r--CanController/S-Car_DoorLeftOFF.pngbin0 -> 1945 bytes
-rw-r--r--CanController/S-Car_DoorLeftON.pngbin0 -> 1969 bytes
-rw-r--r--CanController/S-Car_DoorRightOFF.pngbin0 -> 1910 bytes
-rw-r--r--CanController/S-Car_DoorRightON.pngbin0 -> 1933 bytes
-rw-r--r--CanController/S-Car_HoodOFF.pngbin0 -> 2872 bytes
-rw-r--r--CanController/S-Car_HoodON.pngbin0 -> 2894 bytes
-rw-r--r--CanController/S-Car_LowBeamsOFF.pngbin0 -> 2049 bytes
-rw-r--r--CanController/S-Car_LowBeamsON.pngbin0 -> 2041 bytes
-rw-r--r--CanController/S-Car_Shape.pngbin0 -> 6626 bytes
-rw-r--r--CanController/S-Car_TrunkOFF.pngbin0 -> 1898 bytes
-rw-r--r--CanController/S-Car_TrunkON.pngbin0 -> 1891 bytes
-rw-r--r--CanController/S-Car_TurnLeftOFF.pngbin0 -> 2090 bytes
-rw-r--r--CanController/S-Car_TurnLeftON.pngbin0 -> 2163 bytes
-rw-r--r--CanController/S-Car_TurnRightOFF.pngbin0 -> 2076 bytes
-rw-r--r--CanController/S-Car_TurnRightON.pngbin0 -> 2097 bytes
-rw-r--r--CanController/Slide.qml163
-rw-r--r--CanController/SlideHolder.qml60
-rw-r--r--CanController/ViewChange.qml85
-rw-r--r--CanController/canclusterdatacontrol.cpp934
-rw-r--r--CanController/canclusterdatacontrol.h123
-rw-r--r--CanController/carui.qrc70
-rw-r--r--CanController/clusterdatacontrolinterface.h184
-rw-r--r--CanController/gpssender.cpp139
-rw-r--r--CanController/gpssender.h72
-rw-r--r--CanController/main.cpp86
-rw-r--r--CanController/nmea.cpp446
-rw-r--r--CanController/nmea.h104
-rw-r--r--CanController/route.txt1188
-rw-r--r--CanController/tcpclusterdatacontrol.cpp554
-rw-r--r--CanController/tcpclusterdatacontrol.h123
-rw-r--r--CanController/valuetypes.h77
-rw-r--r--CenterConsole/CenterConsole.pro10
-rw-r--r--CenterConsole/apps/com.pelagicore.media/AlbumScreen.qml178
-rw-r--r--CenterConsole/apps/com.pelagicore.media/ClusterWidget.qml131
-rw-r--r--CenterConsole/apps/com.pelagicore.media/ClusterWidgetGradient.pngbin0 -> 23736 bytes
-rw-r--r--CenterConsole/apps/com.pelagicore.media/CoverItem.qml82
-rw-r--r--CenterConsole/apps/com.pelagicore.media/CurrentTrackScreen.qml245
-rw-r--r--CenterConsole/apps/com.pelagicore.media/Library.qml60
-rw-r--r--CenterConsole/apps/com.pelagicore.media/LibraryList.qml142
-rw-r--r--CenterConsole/apps/com.pelagicore.media/MediaSelectionWidget.qml87
-rw-r--r--CenterConsole/apps/com.pelagicore.media/MoviePlayer.qml148
-rw-r--r--CenterConsole/apps/com.pelagicore.media/MovieProvider.qml83
-rw-r--r--CenterConsole/apps/com.pelagicore.media/Music.qml86
-rw-r--r--CenterConsole/apps/com.pelagicore.media/MusicProvider.qml163
-rw-r--r--CenterConsole/apps/com.pelagicore.media/PassengerWidget.qml73
-rw-r--r--CenterConsole/apps/com.pelagicore.media/PlaylistContainer.qml144
-rw-r--r--CenterConsole/apps/com.pelagicore.media/icon.pngbin0 -> 1913 bytes
-rw-r--r--CenterConsole/apps/com.pelagicore.media/info.yaml12
-rw-r--r--CenterConsole/apps/com.pelagicore.media/qmldir3
-rw-r--r--CenterConsole/apps/com.qtcompany.calendar/Calendar.qml145
-rw-r--r--CenterConsole/apps/com.qtcompany.calendar/ClusterWidget.qml127
-rw-r--r--CenterConsole/apps/com.qtcompany.calendar/icon.pngbin0 -> 2303 bytes
-rw-r--r--CenterConsole/apps/com.qtcompany.calendar/info.yaml13
-rw-r--r--CenterConsole/apps/com.qtcompany.carinfo/CarInfoField.qml56
-rw-r--r--CenterConsole/apps/com.qtcompany.carinfo/Carinfo.qml113
-rw-r--r--CenterConsole/apps/com.qtcompany.carinfo/ClusterWidget.qml111
-rw-r--r--CenterConsole/apps/com.qtcompany.carinfo/icon.pngbin0 -> 2303 bytes
-rw-r--r--CenterConsole/apps/com.qtcompany.carinfo/info.yaml13
-rw-r--r--CenterConsole/apps/com.qtcompany.contacts/ClusterWidget.qml113
-rw-r--r--CenterConsole/apps/com.qtcompany.contacts/Contacts.qml154
-rw-r--r--CenterConsole/apps/com.qtcompany.contacts/icon.pngbin0 -> 2303 bytes
-rw-r--r--CenterConsole/apps/com.qtcompany.contacts/info.yaml13
-rw-r--r--CenterConsole/deployment.pri13
-rw-r--r--CenterConsole/images.qrc25
-rw-r--r--CenterConsole/main.cpp63
-rw-r--r--CenterConsole/plugins/clusterdatasource/clusterdatabackend.cpp736
-rw-r--r--CenterConsole/plugins/clusterdatasource/clusterdatabackend.h139
-rw-r--r--CenterConsole/plugins/clusterdatasource/clusterdatasource.pro31
-rw-r--r--CenterConsole/plugins/clusterdatasource/plugin.cpp56
-rw-r--r--CenterConsole/plugins/clusterdatasource/qmldir2
-rw-r--r--CenterConsole/plugins/clusterdatasource/qtiviclusterdata.cpp388
-rw-r--r--CenterConsole/plugins/clusterdatasource/qtiviclusterdata.h189
-rw-r--r--CenterConsole/plugins/datasource/datasource.cpp46
-rw-r--r--CenterConsole/plugins/datasource/datasource.h49
-rw-r--r--CenterConsole/plugins/datasource/datasource.pro30
-rw-r--r--CenterConsole/plugins/datasource/plugin.cpp45
-rw-r--r--CenterConsole/plugins/datasource/plugin.h45
-rw-r--r--CenterConsole/plugins/datasource/qmldir3
-rw-r--r--CenterConsole/plugins/datasource/sqlquerydatasource.cpp154
-rw-r--r--CenterConsole/plugins/datasource/sqlquerydatasource.h96
-rw-r--r--CenterConsole/plugins/datasource/sqlquerymodel.cpp75
-rw-r--r--CenterConsole/plugins/datasource/sqlquerymodel.h50
-rw-r--r--CenterConsole/plugins/datasource/sqltabledatasource.cpp199
-rw-r--r--CenterConsole/plugins/datasource/sqltabledatasource.h99
-rw-r--r--CenterConsole/plugins/datasource/sqltablemodel.cpp93
-rw-r--r--CenterConsole/plugins/datasource/sqltablemodel.h57
-rw-r--r--CenterConsole/plugins/plugins.pro6
-rw-r--r--CenterConsole/plugins/screenManager/plugin.cpp57
-rw-r--r--CenterConsole/plugins/screenManager/qmldir2
-rw-r--r--CenterConsole/plugins/screenManager/screenManager.pro23
-rw-r--r--CenterConsole/plugins/screenManager/screenmanager.cpp61
-rw-r--r--CenterConsole/plugins/screenManager/screenmanager.h54
-rw-r--r--CenterConsole/plugins/scripts/README.md9
-rw-r--r--CenterConsole/plugins/scripts/scanmovies.py123
-rw-r--r--CenterConsole/plugins/scripts/scanmusic.py149
-rw-r--r--CenterConsole/qml.qrc3
-rw-r--r--CenterConsole/sysui/BottomBar/Aircondition.qml202
-rw-r--r--CenterConsole/sysui/BottomBar/AirflowItem.qml54
-rw-r--r--CenterConsole/sysui/BottomBar/BottomBar.qml86
-rw-r--r--CenterConsole/sysui/BottomBar/ButtonTool.qml61
-rw-r--r--CenterConsole/sysui/BottomBar/TumblerTool.qml80
-rw-r--r--CenterConsole/sysui/CenterItems/ArrivalInfo.qml47
-rw-r--r--CenterConsole/sysui/CenterItems/DestinationInfo.qml117
-rw-r--r--CenterConsole/sysui/CenterItems/HandwritingModeButton.qml169
-rw-r--r--CenterConsole/sysui/CenterItems/MapPOI.qml62
-rw-r--r--CenterConsole/sysui/CenterItems/MapPage.qml424
-rw-r--r--CenterConsole/sysui/CenterItems/SearchInput.qml223
-rw-r--r--CenterConsole/sysui/CenterItems/SuggestedPlaces.qml69
-rw-r--r--CenterConsole/sysui/CenterItems/offlineRoute.txt272
-rw-r--r--CenterConsole/sysui/CenterItems/route.txt1016
-rw-r--r--CenterConsole/sysui/CenterScreen.qml194
-rw-r--r--CenterConsole/sysui/Keyboard.qml40
-rw-r--r--CenterConsole/sysui/LaunchController.qml89
-rw-r--r--CenterConsole/sysui/Launcher/CalendarWidget.qml36
-rw-r--r--CenterConsole/sysui/Launcher/CarInfoWidget.qml41
-rw-r--r--CenterConsole/sysui/Launcher/ContactsWidget.qml40
-rw-r--r--CenterConsole/sysui/Launcher/LauncherBar.qml78
-rw-r--r--CenterConsole/sysui/Launcher/MusicWidget.qml133
-rw-r--r--CenterConsole/sysui/StatusBar/DateAndTime.qml64
-rw-r--r--CenterConsole/sysui/StatusBar/StatusBar.qml74
-rw-r--r--Cluster/Cluster.pro8
-rw-r--r--Cluster/images.qrc23
-rw-r--r--Cluster/images/BackgroundGradient.pngbin0 -> 18682 bytes
-rw-r--r--Cluster/images/BottomPanel.pngbin0 -> 27556 bytes
-rw-r--r--Cluster/images/Built_with_Qt_RGB_logo_white.pngbin0 -> 10082 bytes
-rw-r--r--Cluster/images/Cluster8Gauges.pngbin0 -> 691473 bytes
-rw-r--r--Cluster/images/Cluster8GaugesPlain.pngbin0 -> 656289 bytes
-rw-r--r--Cluster/images/ClusterGaugeCenters.pngbin0 -> 59985 bytes
-rw-r--r--Cluster/images/ClusterGaugeCentersPlain.pngbin0 -> 31938 bytes
-rw-r--r--Cluster/images/Gauges_normal.pngbin0 -> 473434 bytes
-rw-r--r--Cluster/images/Icon_Battery_OFF.pngbin0 -> 1307 bytes
-rw-r--r--Cluster/images/Icon_Battery_ON.pngbin0 -> 1933 bytes
-rw-r--r--Cluster/images/Icon_BulbFailure_OFF.pngbin0 -> 1940 bytes
-rw-r--r--Cluster/images/Icon_BulbFailure_ON.pngbin0 -> 2711 bytes
-rw-r--r--Cluster/images/Icon_Coolant_OFF.pngbin0 -> 1563 bytes
-rw-r--r--Cluster/images/Icon_Coolant_ON.pngbin0 -> 2024 bytes
-rw-r--r--Cluster/images/Icon_Fuel_OFF.pngbin0 -> 1485 bytes
-rw-r--r--Cluster/images/Icon_Fuel_ON.pngbin0 -> 1969 bytes
-rw-r--r--Cluster/images/Icon_LowBeam_OFF.pngbin0 -> 1853 bytes
-rw-r--r--Cluster/images/Icon_LowBeam_ON.pngbin0 -> 2323 bytes
-rw-r--r--Cluster/images/Icon_ParkingBrake_OFF.pngbin0 -> 1962 bytes
-rw-r--r--Cluster/images/Icon_ParkingBrake_ON.pngbin0 -> 2448 bytes
-rw-r--r--Cluster/images/Icon_PositionLights_OFF.pngbin0 -> 1617 bytes
-rw-r--r--Cluster/images/Icon_PositionLights_ON.pngbin0 -> 2085 bytes
-rw-r--r--Cluster/images/Icon_SeatBelt_OFF.pngbin0 -> 1539 bytes
-rw-r--r--Cluster/images/Icon_SeatBelt_ON.pngbin0 -> 1956 bytes
-rw-r--r--Cluster/images/Icon_TurnLeft_OFF.pngbin0 -> 1339 bytes
-rw-r--r--Cluster/images/Icon_TurnLeft_ON.pngbin0 -> 2119 bytes
-rw-r--r--Cluster/images/Icon_TyreMalfunction_OFF.pngbin0 -> 1584 bytes
-rw-r--r--Cluster/images/Icon_TyreMalfunction_ON.pngbin0 -> 2145 bytes
-rw-r--r--Cluster/images/SpeedometerNeedle.pngbin0 -> 280 bytes
-rw-r--r--Cluster/images/status_battery_highlight.pngbin0 -> 275 bytes
-rw-r--r--Cluster/images/status_battery_icon.pngbin0 -> 1425 bytes
-rw-r--r--Cluster/images/status_washer_fluid_highlight.pngbin0 -> 602 bytes
-rw-r--r--Cluster/images/status_washer_fluid_icon.pngbin0 -> 2128 bytes
-rw-r--r--Cluster/images/welcomeview_passenger_icon.pngbin0 -> 958 bytes
-rw-r--r--Cluster/images/welcomeview_status_icon.pngbin0 -> 1334 bytes
-rw-r--r--Cluster/images/welcomeview_trip_info_icon.pngbin0 -> 1336 bytes
-rw-r--r--Cluster/images/welcomeview_trip_route.pngbin0 -> 7123 bytes
-rw-r--r--Cluster/main.cpp130
-rw-r--r--Cluster/plugins/gaugefiller/gauge.cpp264
-rw-r--r--Cluster/plugins/gaugefiller/gauge.h138
-rw-r--r--Cluster/plugins/gaugefiller/gaugefiller.pro23
-rw-r--r--Cluster/plugins/gaugefiller/gaugenode.cpp306
-rw-r--r--Cluster/plugins/gaugefiller/gaugenode.h164
-rw-r--r--Cluster/plugins/gaugefiller/plugin.cpp52
-rw-r--r--Cluster/plugins/gaugefiller/qmldir2
-rw-r--r--Cluster/plugins/plugins.pro5
-rw-r--r--Cluster/plugins/scenehelper/plugin.cpp52
-rw-r--r--Cluster/plugins/scenehelper/qmldir2
-rw-r--r--Cluster/plugins/scenehelper/scenehelper.cpp194
-rw-r--r--Cluster/plugins/scenehelper/scenehelper.h65
-rw-r--r--Cluster/plugins/scenehelper/scenehelper.pro22
-rw-r--r--Cluster/qml/BottomPanel.qml134
-rw-r--r--Cluster/qml/CarModel.qml551
-rw-r--r--Cluster/qml/CenterView.qml152
-rw-r--r--Cluster/qml/Dashboard.qml289
-rw-r--r--Cluster/qml/DashboardFrame.qml121
-rw-r--r--Cluster/qml/DashboardView.qml49
-rw-r--r--Cluster/qml/FpsCounter.qml87
-rw-r--r--Cluster/qml/TurnIndicator.qml60
-rw-r--r--Cluster/qml/WelcomeDriver.qml105
-rw-r--r--Cluster/qml/WelcomeInfoNote.qml67
-rw-r--r--Cluster/qml/WelcomeStatus.qml118
-rw-r--r--Cluster/qml/WelcomeStatusNote.qml76
-rw-r--r--Cluster/qml/WelcomeTripSummary.qml113
-rw-r--r--Cluster/qml/WelcomeView.qml232
-rw-r--r--Cluster/qml/gauges/BatteryMeter.qml56
-rw-r--r--Cluster/qml/gauges/ConsumptionMeter.qml74
-rw-r--r--Cluster/qml/gauges/FpsMeter.qml72
-rw-r--r--Cluster/qml/gauges/FuelMeter.qml56
-rw-r--r--Cluster/qml/gauges/SpeedoMeter.qml138
-rw-r--r--Cluster/qml/gauges/TachoMeter.qml96
-rw-r--r--Cluster/qml/gauges/TemperatureMeter.qml75
-rw-r--r--Cluster/qml/gauges/TurboMeter.qml56
-rw-r--r--Cluster/qml/models/Map11.jpgbin0 -> 58551 bytes
-rw-r--r--Cluster/qml/models/sportscar.qgltfbin0 -> 59572 bytes
-rw-r--r--Cluster/qml/models/sportscar_1.binbin0 -> 2899794 bytes
-rw-r--r--Cluster/qtcluster.qrc13
-rw-r--r--Cluster/sportscar.qrc7
-rw-r--r--Cluster/sportscar_15k.qrc7
-rw-r--r--Cluster/sportsimages.qrc5
-rw-r--r--Cluster/sportsqml.qrc8
-rw-r--r--LICENSE.GPL3-EXCEPT704
-rw-r--r--Main.qml131
-rw-r--r--MainWithClusterAndPassenger.qml85
-rw-r--r--PassengerView/PassengerView.qml64
-rw-r--r--README74
-rw-r--r--am-config.yaml32
-rw-r--r--automotivedemo.pro17
-rw-r--r--defaults.pri6
m---------demo-assets0
-rw-r--r--deployment.pri3
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/backspace-868482.svg75
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/check-868482.svg8
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/enter-868482.svg13
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/globe-868482.svg56
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/handwriting-868482.svg54
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/hidekeyboard-868482.svg281
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/search-868482.svg14
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-80c342.pngbin0 -> 906 bytes
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-868482.svg12
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-c5d6b6.svg12
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/textmode-868482.svg87
-rw-r--r--imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/style.qml888
-rw-r--r--imports/shared/assets/drawable-ldpi/FloatingButton_Active.svg41
-rw-r--r--imports/shared/assets/drawable-ldpi/FloatingButton_Available.svg41
-rw-r--r--imports/shared/assets/drawable-ldpi/FloatingButton_Unavailable.svg39
-rw-r--r--imports/shared/assets/icons/4g-signal-strength.pngbin0 -> 162 bytes
-rw-r--r--imports/shared/assets/icons/Built_with_Qt_RGB_logo_white.pngbin0 -> 5641 bytes
-rw-r--r--imports/shared/assets/icons/CarFocusButton.pngbin0 -> 27596 bytes
-rw-r--r--imports/shared/assets/icons/CarInfo.pngbin0 -> 18254 bytes
-rw-r--r--imports/shared/assets/icons/FullScreenGradient.pngbin0 -> 8315287 bytes
-rw-r--r--imports/shared/assets/icons/Highlight.pngbin0 -> 7346 bytes
-rw-r--r--imports/shared/assets/icons/MapOverlayEdgeGradient.pngbin0 -> 23564 bytes
-rw-r--r--imports/shared/assets/icons/MiddleMask.pngbin0 -> 230195 bytes
-rw-r--r--imports/shared/assets/icons/MusicOverlayGradient.pngbin0 -> 7293 bytes
-rw-r--r--imports/shared/assets/icons/MusicOverlayGradient2.pngbin0 -> 10917 bytes
-rw-r--r--imports/shared/assets/icons/NavRoundmarker.pngbin0 -> 21011 bytes
-rw-r--r--imports/shared/assets/icons/RectangleGradient256x512.pngbin0 -> 4373 bytes
-rw-r--r--imports/shared/assets/icons/SimpleBottomBackground.pngbin0 -> 1187751 bytes
-rw-r--r--imports/shared/assets/icons/acautosync-knob-down.pngbin0 -> 37727 bytes
-rw-r--r--imports/shared/assets/icons/acautosync-knob-up.pngbin0 -> 14943 bytes
-rw-r--r--imports/shared/assets/icons/back-background.pngbin0 -> 4982 bytes
-rw-r--r--imports/shared/assets/icons/back.pngbin0 -> 381 bytes
-rw-r--r--imports/shared/assets/icons/background-contacts.pngbin0 -> 16624 bytes
-rw-r--r--imports/shared/assets/icons/bluetooth.pngbin0 -> 768 bytes
-rw-r--r--imports/shared/assets/icons/calendar.pngbin0 -> 20646 bytes
-rw-r--r--imports/shared/assets/icons/cancel.pngbin0 -> 633 bytes
-rw-r--r--imports/shared/assets/icons/car-info.pngbin0 -> 3276 bytes
-rw-r--r--imports/shared/assets/icons/contacts.pngbin0 -> 2923 bytes
-rw-r--r--imports/shared/assets/icons/destination-airport.pngbin0 -> 809 bytes
-rw-r--r--imports/shared/assets/icons/destination-home.pngbin0 -> 551 bytes
-rw-r--r--imports/shared/assets/icons/destination-work.pngbin0 -> 450 bytes
-rw-r--r--imports/shared/assets/icons/fandirection-head.pngbin0 -> 2008 bytes
-rw-r--r--imports/shared/assets/icons/fandirection-headandlegs.pngbin0 -> 2245 bytes
-rw-r--r--imports/shared/assets/icons/fandirection-knob-down.pngbin0 -> 51433 bytes
-rw-r--r--imports/shared/assets/icons/fandirection-knob-up.pngbin0 -> 53297 bytes
-rw-r--r--imports/shared/assets/icons/fandirection-legs.pngbin0 -> 1949 bytes
-rw-r--r--imports/shared/assets/icons/fandirection-windshield.pngbin0 -> 2136 bytes
-rw-r--r--imports/shared/assets/icons/fandirection-windshieldandlegs.pngbin0 -> 2371 bytes
-rw-r--r--imports/shared/assets/icons/fandirection.pngbin0 -> 1454 bytes
-rw-r--r--imports/shared/assets/icons/jane.pngbin0 -> 26924 bytes
-rw-r--r--imports/shared/assets/icons/john.pngbin0 -> 16003 bytes
-rw-r--r--imports/shared/assets/icons/music.pngbin0 -> 1913 bytes
-rw-r--r--imports/shared/assets/icons/placeofinterest-charging.pngbin0 -> 667 bytes
-rw-r--r--imports/shared/assets/icons/placeofinterest-coffee.pngbin0 -> 1385 bytes
-rw-r--r--imports/shared/assets/icons/placeofinterest-parking.pngbin0 -> 963 bytes
-rw-r--r--imports/shared/assets/icons/placeofinterest-shopping.pngbin0 -> 1014 bytes
-rw-r--r--imports/shared/assets/icons/screencast.pngbin0 -> 723 bytes
-rw-r--r--imports/shared/assets/icons/search.pngbin0 -> 17167 bytes
-rw-r--r--imports/shared/assets/icons/video-next.pngbin0 -> 641 bytes
-rw-r--r--imports/shared/assets/icons/video-pause.pngbin0 -> 168 bytes
-rw-r--r--imports/shared/assets/icons/video-play.pngbin0 -> 815 bytes
-rw-r--r--imports/shared/assets/icons/video-previous.pngbin0 -> 647 bytes
-rw-r--r--imports/shared/assets/icons/video.pngbin0 -> 1487 bytes
-rw-r--r--imports/shared/assets/icons/wifi-signal-strength.pngbin0 -> 779 bytes
-rw-r--r--imports/shared/controls/AppStackView.qml86
-rw-r--r--imports/shared/controls/Button_neptune.qml91
-rw-r--r--imports/shared/controls/DisplayBackground.qml43
-rw-r--r--imports/shared/controls/Icon.qml53
-rw-r--r--imports/shared/controls/Label.qml43
-rw-r--r--imports/shared/controls/LaunchItemBackground.qml62
-rw-r--r--imports/shared/controls/Slider.qml118
-rw-r--r--imports/shared/controls/SwipeView.qml80
-rw-r--r--imports/shared/controls/Symbol.qml51
-rw-r--r--imports/shared/controls/Tool.qml63
-rw-r--r--imports/shared/controls/qmldir14
-rw-r--r--imports/shared/service/climate/ClimateService.qml134
-rw-r--r--imports/shared/service/climate/ClimateStateMachine.qml169
-rw-r--r--imports/shared/service/climate/qmldir1
-rw-r--r--imports/shared/service/movie/MovieService.qml67
-rw-r--r--imports/shared/service/movie/qmldir1
-rw-r--r--imports/shared/service/music/MusicService.qml118
-rw-r--r--imports/shared/service/music/qmldir1
-rw-r--r--imports/shared/service/settings/SettingsService.qml124
-rw-r--r--imports/shared/service/settings/qmldir1
-rw-r--r--imports/shared/service/statusbar/StatusBarService.qml60
-rw-r--r--imports/shared/service/statusbar/qmldir1
-rw-r--r--imports/shared/service/valuesource/ValueSource.qml282
-rw-r--r--imports/shared/service/valuesource/qmldir1
-rw-r--r--imports/shared/utils/AppUIScreen.qml109
-rw-r--r--imports/shared/utils/AutoConfig.qml118
-rw-r--r--imports/shared/utils/Spacer.qml51
-rw-r--r--imports/shared/utils/Style.qml227
-rw-r--r--imports/shared/utils/Tracer.qml62
-rw-r--r--imports/shared/utils/UIElement.qml47
-rw-r--r--imports/shared/utils/UIScreen.qml70
-rw-r--r--imports/shared/utils/qmldir12
-rw-r--r--imports/system/models/ApplicationManagerInterface.qml173
-rw-r--r--imports/system/models/qmldir1
-rw-r--r--kms_config.json14
-rw-r--r--scripts/automotivedemo.service9
-rw-r--r--start.sh5
364 files changed, 24897 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ddb4800
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,64 @@
+*.swp
+*~
+*.user
+*.user.*
+tmp
+Makefile*
+*.pdb
+bin/*
+include/*
+*_resource.rc
+*~
+*.a
+*.la
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+.qmake.cache
+.qmake.vars
+*.prl
+moc_*.cpp
+qrc_*.cpp
+ui_*.h
+*.qmlc
+
+# Directories to ignore
+.moc
+.rcc
+.uic
+.pch
+build-*
+
+# Test generated files
+tst_*
+!tst_*.*
+tst_*.log
+tst_*.debug
+tst_*~
+tests/auto/cmake/build
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.vcxproj
+*.vcxproj.filters
+*.vcxproj.user
+
+# MinGW generated files
+*.Debug
+*.Release
+
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..aa1c8f0
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "demo-assets"]
+ path = demo-assets
+ url = ../demo-assets.git
diff --git a/CanController/Button.qml b/CanController/Button.qml
new file mode 100644
index 0000000..01f8a7f
--- /dev/null
+++ b/CanController/Button.qml
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: buttonMainRect
+ width: 80
+ height: 50
+ radius: 5
+ border.width: 2
+
+ property color blinkColor: "#26282a"
+ property color textBlinkColor: "#d6d6d6"
+
+ // color: (buttonMainRect.blink ? "pink" : "white")
+
+ property alias text: buttonText.text
+ property alias textColor: buttonText.color
+ property alias fontPixelSize: buttonText.font.pixelSize
+ property string icon
+ property string iconPressed
+ property bool pressed: false
+ property bool blink: false
+ property bool blinkingEnabled: false
+ property alias mouseEnabled: buttonMouse.enabled
+ function synchronize() {
+ blinkTimer.restart()
+ }
+
+ onPressedChanged: {
+ if (buttonMainRect.pressed) {
+ if (buttonMainRect.blinkingEnabled) {
+ blinkTimer.start()
+ } else {
+ buttonMainRect.color = buttonMainRect.blinkColor
+ buttonText.color = buttonMainRect.textBlinkColor
+ }
+ }
+ else {
+ if (buttonMainRect.blinkingEnabled)
+ blinkTimer.stop()
+ buttonMainRect.color = blinkTimer.baseColor
+ buttonText.color = blinkTimer.textBaseColor
+ }
+ }
+
+ Text {
+ id: buttonText
+ anchors.centerIn: parent
+ visible: !buttonImage.visible
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 14
+ color: "#26282a"
+ }
+
+ Image {
+ id: buttonImage
+ visible: (buttonImage.source != "")
+ anchors.centerIn: parent
+ source: (buttonMainRect.pressed ? buttonMainRect.iconPressed : buttonMainRect.icon)
+ }
+
+ MouseArea {
+ id: buttonMouse
+ anchors.fill: parent
+ onClicked: buttonMainRect.pressed = !buttonMainRect.pressed
+ }
+
+ Timer {
+ id: blinkTimer
+ repeat: true
+ onRunningChanged: {
+ if (!blinkTimer.running && buttonMainRect.blink)
+ buttonMainRect.blink = false
+ }
+ property color baseColor
+ property color textBaseColor
+ Component.onCompleted: {
+ blinkTimer.baseColor = buttonMainRect.color
+ blinkTimer.textBaseColor = buttonText.color
+ }
+ interval: 300
+ onTriggered: {
+ buttonMainRect.blink = !buttonMainRect.blink
+ if (buttonMainRect.blink) {
+ buttonMainRect.color = buttonMainRect.blinkColor
+ buttonText.color = buttonMainRect.textBlinkColor
+ } else {
+ buttonMainRect.color = blinkTimer.baseColor
+ buttonText.color = blinkTimer.textBaseColor
+ }
+ }
+ }
+}
diff --git a/CanController/ButtonHolder.qml b/CanController/ButtonHolder.qml
new file mode 100644
index 0000000..9959215
--- /dev/null
+++ b/CanController/ButtonHolder.qml
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ width: 80
+ height: 85
+ property alias icon: buttonHolderButton.icon
+ property alias iconPressed: buttonHolderButton.iconPressed
+ property alias text: buttonHolderText.text
+ property alias blinkingEnabled: buttonHolderButton.blinkingEnabled
+ property alias pressed: buttonHolderButton.pressed
+ property alias mouseEnabled: buttonHolderButton.mouseEnabled
+
+ function synchronize() {
+ buttonHolderButton.synchronize()
+ }
+
+ Button {
+ id: buttonHolderButton
+ }
+
+ Text {
+ id: buttonHolderText
+ anchors {
+ top: buttonHolderButton.bottom
+ topMargin: 7
+ horizontalCenter: parent.horizontalCenter
+ }
+ font.pixelSize: 12
+ }
+}
diff --git a/CanController/CanController.pro b/CanController/CanController.pro
new file mode 100644
index 0000000..bf271bc
--- /dev/null
+++ b/CanController/CanController.pro
@@ -0,0 +1,39 @@
+QT = core gui quick qml
+DISTFILES += \
+ CarUI.qml \
+ Button.qml \
+ Slide.qml \
+ Blinks.qml \
+ Car.qml \
+ Gear.qml \
+ GearAutomatic.qml \
+ ButtonHolder.qml \
+ SlideHolder.qml \
+ ViewChange.qml
+
+DEFINES += TCPCLUSTERDATACONNECTION
+SOURCES += \
+ tcpclusterdatacontrol.cpp
+HEADERS += \
+ tcpclusterdatacontrol.h
+
+SOURCES += \
+ main.cpp \
+ gpssender.cpp \
+ nmea.cpp
+
+HEADERS += \
+ clusterdatacontrolinterface.h \
+ gpssender.h \
+ nmea.h \
+ valuetypes.h
+
+RESOURCES += carui.qrc
+
+DEFINES += MAIN_QML_FILE_NAME=\\\"qrc:/CarUI.qml\\\" DEFAULT_ROUTE_FILE=\\\":/route.txt\\\"
+
+TEMPLATE = app
+TARGET = carui
+
+target.path = /data/user/qt/$$TARGET
+INSTALLS += target
diff --git a/CanController/Car.qml b/CanController/Car.qml
new file mode 100644
index 0000000..8036cb2
--- /dev/null
+++ b/CanController/Car.qml
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ id: carFrame
+
+ width: electricCar ? carShapeElectric.width : carShape.width
+ height: electricCar ? carShapeElectric.height : carShape.height
+
+ property bool electricCar: false
+
+ property bool headLight: false
+ property bool leftBlink: false
+ property bool rightBlink: false
+ property bool breakLight: false
+
+ property bool leftFrontDoorOpen: false
+ property bool leftBackDoorOpen: false
+ property bool rightFrontDoorOpen: false
+ property bool rightBackDoorOpen: false
+ property bool bootDoorOpen: false
+ property bool hoodDoorOpen: false
+
+ // Sports Car
+ Image {
+ id: carShape
+ visible: !electricCar
+ source: "qrc:/S-Car_Shape.png"
+ }
+ Image {
+ visible: !electricCar
+ source: breakLight ? "qrc:/S-Car_BrakesON.png" : "qrc:/S-Car_BrakesOFF.png"
+ }
+ Image {
+ visible: !electricCar
+ source: leftFrontDoorOpen ? "qrc:/S-Car_DoorLeftON.png" : "qrc:/S-Car_DoorLeftOFF.png"
+ }
+ Image {
+ visible: !electricCar
+ source: rightFrontDoorOpen ? "qrc:/S-Car_DoorRightON.png" : "qrc:/S-Car_DoorRightOFF.png"
+ }
+ Image {
+ visible: !electricCar
+ source: hoodDoorOpen ? "qrc:/S-Car_HoodON.png" : "qrc:/S-Car_HoodOFF.png"
+ }
+ Image {
+ visible: !electricCar
+ source: headLight ? "qrc:/S-Car_LowBeamsON.png" : "qrc:/S-Car_LowBeamsOFF.png"
+ }
+ Image {
+ visible: !electricCar
+ source: bootDoorOpen ? "qrc:/S-Car_TrunkON.png" : "qrc:/S-Car_TrunkOFF.png"
+ }
+ Image {
+ visible: !electricCar
+ source: leftBlink ? "qrc:/S-Car_TurnLeftON.png" : "qrc:/S-Car_TurnLeftOFF.png"
+ }
+ Image {
+ visible: !electricCar
+ source: rightBlink ? "qrc:/S-Car_TurnRightON.png" : "qrc:/S-Car_TurnRightOFF.png"
+ }
+
+ // Electric Car
+ Image {
+ id: carShapeElectric
+ visible: electricCar
+ source: "qrc:/E-Car_Shape.png"
+ }
+ Image {
+ visible: electricCar
+ source: breakLight ? "qrc:/E-Car_BrakesON.png" : "qrc:/E-Car_BrakesOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: leftFrontDoorOpen ? "qrc:/E-Car_FrontDoorLeftON.png"
+ : "qrc:/E-Car_FrontDoorLeftOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: rightFrontDoorOpen ? "qrc:/E-Car_FrontDoorRightON.png"
+ : "qrc:/E-Car_FrontDoorRightOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: leftBackDoorOpen ? "qrc:/E-Car_BackDoorLeftON.png"
+ : "qrc:/E-Car_BackDoorLeftOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: rightBackDoorOpen ? "qrc:/E-Car_BackDoorRightON.png"
+ : "qrc:/E-Car_BackDoorRightOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: hoodDoorOpen ? "qrc:/E-Car_HoodON.png" : "qrc:/E-Car_HoodOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: headLight ? "qrc:/E-Car_LowBeamsON.png" : "qrc:/E-Car_LowBeamsOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: bootDoorOpen ? "qrc:/E-Car_TrunkON.png" : "qrc:/E-Car_TrunkOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: leftBlink ? "qrc:/E-Car_TurnLeftON.png" : "qrc:/E-Car_TurnLeftOFF.png"
+ }
+ Image {
+ visible: electricCar
+ source: rightBlink ? "qrc:/E-Car_TurnRightON.png" : "qrc:/E-Car_TurnRightOFF.png"
+ }
+}
diff --git a/CanController/CarUI.qml b/CanController/CarUI.qml
new file mode 100644
index 0000000..b948515
--- /dev/null
+++ b/CanController/CarUI.qml
@@ -0,0 +1,462 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 1024
+ height: 768
+
+ property int carNumber: 2
+
+ Rectangle {
+ id: leftBackgroundRect
+ anchors {
+ top: parent.top
+ left: parent.left
+ bottom: parent.bottom
+ }
+ width: 353
+ color: "#484950"
+
+ Car {
+ id: car
+ anchors {
+ top: parent.top
+ topMargin: 20
+ horizontalCenter: parent.horizontalCenter
+ }
+
+ electricCar: carNumber === 0
+ headLight: clusterDataControl.headLight
+ //breakLight: brakeLights.pressed
+
+ leftFrontDoorOpen: clusterDataControl.frontLeftDoorOpen
+ leftBackDoorOpen: clusterDataControl.rearLeftDoorOpen
+ rightFrontDoorOpen: clusterDataControl.frontRightDoorOpen
+ rightBackDoorOpen: clusterDataControl.rearRightDoorOpen
+ bootDoorOpen: bootDoorButton.pressed//clusterDataControl.trunkOpen
+ hoodDoorOpen: clusterDataControl.hoodOpen
+ leftBlink: clusterDataControl.leftTurnLight
+ rightBlink: clusterDataControl.rightTurnLight
+ }
+
+ Gear {
+ id: gearController
+ visible: carNumber === 1
+ gear: 1
+ anchors {
+ top: car.bottom
+ topMargin: 33
+ horizontalCenter: parent.horizontalCenter
+ }
+ onGearChanged: clusterDataControl.gear = gearController.gear
+ }
+
+ GearAutomatic {
+ id: gearControllerAutomatic
+ visible: carNumber !== 1
+ gear: 1
+ anchors {
+ top: car.bottom
+ topMargin: 33
+ horizontalCenter: parent.horizontalCenter
+ }
+ onGearChanged: {
+ if (gear !== 0 && brakeLights.pressed)
+ brakeLights.pressed = false
+ clusterDataControl.gear = gearControllerAutomatic.gear
+ }
+ }
+
+ Button {
+ id: carID
+ visible: false
+ anchors {
+ top: (carNumber === 1) ? gearController.bottom : gearControllerAutomatic.bottom
+ topMargin: 33
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: 240
+ height: 70
+ radius: 6
+ color: "#d6d6d6"
+ textColor: "#26282a"
+ textBlinkColor: "#26282a"
+ blinkColor: "#d6d6d6"
+ fontPixelSize: 23
+ text: "Sports Car"
+ onPressedChanged: {
+ if (++carNumber > 2)
+ carNumber = 0
+ resetButtonStates()
+ clusterDataControl.carId = carNumber
+ if (carNumber === 0)
+ text = "Electric Car"
+ else if (carNumber === 1)
+ text = "Sports Car"
+ else
+ text = "Hybrid Car"
+ }
+ }
+
+ Button {
+ id: demoMode
+ anchors {
+ top: carID.bottom
+ topMargin: 10
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: 240
+ height: 35
+ radius: 6
+ color: "#d6d6d6"
+ textColor: "#26282a"
+ textBlinkColor: "#d6d6d6"
+ blinkColor: "#26282a"
+ fontPixelSize: 14
+ text: "Automatic Demo Mode"
+ onPressedChanged: {
+ clusterDataControl.parkLight = demoMode.pressed
+ }
+ }
+ }
+
+ Rectangle {
+ id: rightBackgroundRect
+ anchors {
+ top: parent.top
+ left: leftBackgroundRect.right
+ right: parent.right
+ bottom: parent.bottom
+ }
+ width: 353
+ color: "#ffffff"
+
+ Grid {
+ id: buttonGrid
+ anchors {
+ top: parent.top
+ topMargin: 42
+ left: parent.left
+ leftMargin: 42
+ right: parent.right
+ rightMargin: 42
+ }
+ spacing: 10
+
+ columns: 7
+ rows: 3
+
+ // 1st row
+ ButtonHolder {
+ id: leftSignalButton
+ icon: "qrc:/Icon_TurnLeft_OFF.png"
+ iconPressed: "qrc:/Icon_TurnLeft_ON.png"
+ text: "Turn Left"
+ blinkingEnabled: false
+ onPressedChanged: {
+ if (!hazardButton.pressed) {
+ if (leftSignalButton.pressed && rightSignalButton.pressed) {
+ rightSignalButton.pressed = false
+ car.rightBlink = false
+ }
+ clusterDataControl.leftTurnLight = leftSignalButton.pressed
+ car.leftBlink = leftSignalButton.pressed
+ }
+ }
+ mouseEnabled: !hazardButton.pressed
+ }
+ ButtonHolder {
+ id: rightSignalButton
+ icon: "qrc:/Icon_TurnRight_OFF.png"
+ iconPressed: "qrc:/Icon_TurnRight_ON.png"
+ text: "Turn Right"
+ blinkingEnabled: false
+ onPressedChanged: {
+ if (!hazardButton.pressed) {
+ if (rightSignalButton.pressed && leftSignalButton.pressed) {
+ leftSignalButton.pressed = false
+ car.leftBlink = false
+ }
+ clusterDataControl.rightTurnLight = rightSignalButton.pressed
+ car.rightBlink = rightSignalButton.pressed
+ }
+ }
+ mouseEnabled: !hazardButton.pressed
+ }
+ ButtonHolder {
+ id: hazardButton
+ icon: "qrc:/Icon_HazardWarning_OFF.png"
+ iconPressed: "qrc:/Icon_HazardWarning_ON.png"
+ text: "Hazard Warning"
+ blinkingEnabled: false
+ property bool leftPreviousState: false
+ property bool rightPreviousState: false
+ onPressedChanged: {
+ clusterDataControl.hazardSignal = hazardButton.pressed
+ if (hazardButton.pressed) {
+ if (leftSignalButton.pressed)
+ hazardButton.leftPreviousState = true
+ else
+ leftSignalButton.pressed = true
+ if (rightSignalButton.pressed)
+ hazardButton.rightPreviousState = true
+ else
+ rightSignalButton.pressed = true
+ } else {
+ if (hazardButton.leftPreviousState)
+ hazardButton.leftPreviousState = false
+ else
+ leftSignalButton.pressed = false
+ if (hazardButton.rightPreviousState)
+ hazardButton.rightPreviousState = false
+ else
+ rightSignalButton.pressed = false
+ }
+ car.leftBlink = leftSignalButton.pressed
+ car.rightBlink = rightSignalButton.pressed
+ }
+ }
+ /*
+ ButtonHolder {
+ id: parkLights
+ text: "Position Lights"
+ onPressedChanged: clusterDataControl.parkLight = parkLights.pressed
+ }
+ */
+ ButtonHolder {
+ id: headLights
+ icon: "qrc:/Icon_LowBeam_OFF.png"
+ iconPressed: "qrc:/Icon_LowBeam_ON.png"
+ text: "Low Beam"
+ onPressedChanged: clusterDataControl.headLight = headLights.pressed
+ }
+ ButtonHolder {
+ id: lampFailureButton
+ icon: "qrc:/Icon_BulbFailure_OFF.png"
+ iconPressed: "qrc:/Icon_BulbFailure_ON.png"
+ text: "Bulb Failure"
+ onPressedChanged: clusterDataControl.lightFailure = pressed
+ }
+ ButtonHolder {
+ id: tireFailureButton
+ text: "Tyre Malfunction"
+ icon: "qrc:/Icon_TyreMalfunction_OFF.png"
+ iconPressed: "qrc:/Icon_TyreMalfunction_ON.png"
+ onPressedChanged: clusterDataControl.flatTire = pressed
+ }
+
+ // 2nd row
+ /*
+ ButtonHolder {
+ text: "Seat Belt"
+ }
+ ButtonHolder {
+ text: "Tyre Malfunction"
+ icon: "qrc:/Icon_TyreMalfunction_OFF.png"
+ iconPressed: "qrc:/Icon_TyreMalfunction_ON.png"
+ }
+ ButtonHolder {
+ text: "Fuel"
+ }
+ */
+ ButtonHolder {
+ id: brakeLights
+ icon: "qrc:/Icon_ParkingBrake_OFF.png"
+ iconPressed: "qrc:/Icon_ParkingBrake_ON.png"
+ text: "Parking Brake"
+ onPressedChanged: {
+ gearController.gear = 0
+ gearControllerAutomatic.gear = 0
+ clusterDataControl.brake = brakeLights.pressed
+ }
+ }
+ /*
+ ButtonHolder {
+ text: "Coolant Temp."
+ }
+ ButtonHolder {
+ text: "Battery"
+ }
+ */
+
+ // 3rd row
+ Button {
+ id: leftFrontDoorButton
+ height: 60
+ text: (carNumber === 0) ? "Left Door\nFRONT" : "Left Door"
+ onPressedChanged: clusterDataControl.frontLeftDoorOpen = pressed
+ visible: carNumber !== 2
+ }
+ Button {
+ id: rightFrontDoorButton
+ height: 60
+ text: (carNumber === 0) ? "Right Door\nFRONT" : "Right Door"
+ onPressedChanged: clusterDataControl.frontRightDoorOpen = pressed
+ visible: carNumber !== 2
+ }
+ Button {
+ id: hoodDoorButton
+ height: 60
+ text: "Hood"
+ onPressedChanged: clusterDataControl.hoodOpen = pressed
+ visible: carNumber !== 2
+ }
+ Button {
+ id: leftBackDoorButton
+ height: 60
+ visible: (carNumber === 0)
+ text: "Left Door\nBACK"
+ onPressedChanged: clusterDataControl.rearLeftDoorOpen = pressed
+ }
+ Button {
+ id: rightBackDoorButton
+ height: 60
+ visible: (carNumber === 0)
+ text: "Right Door\nBACK"
+ onPressedChanged: clusterDataControl.rearRightDoorOpen = pressed
+ }
+ Button {
+ id: bootDoorButton
+ height: 60
+ text: "Trunk"
+ onPressedChanged: clusterDataControl.trunkOpen = pressed
+ visible: carNumber !== 2
+ }
+ }
+ Row {
+ id: viewButtons
+ spacing: 10
+ visible: false // Center view changing is not used with automotivedemo
+ anchors {
+ top: buttonGrid.bottom
+ horizontalCenter: parent.horizontalCenter
+ topMargin: 42
+ }
+ ViewChange {
+ width: 270
+ text: (carNumber === 0) ? "CHANGE LEFT VIEW" : "CHANGE CENTER VIEW"
+ optionalIcons: carNumber === 2
+ }
+ ViewChange {
+ visible: carNumber === 0
+ text: "CHANGE RIGHT VIEW"
+ mainView: false
+ width: 270
+ }
+ }
+
+ Column {
+ anchors {
+ top: viewButtons.bottom
+ topMargin: 42
+ left: parent.left
+ leftMargin: 42
+ right: parent.right
+ rightMargin: 42
+ bottom: parent.bottom
+ bottomMargin: 30
+ }
+ SlideHolder {
+ id: batteryLevel
+ text: "BATTERY CHARGE"
+ max: 100
+ steps: 10
+ value: 80
+ valueStep: 2.5
+ onValueChanged: {
+ // Battery charge vs. battery % level
+ // 12.66 V = 100 %
+ // 12.45 V = 75 %
+ // 12.24 V = 50 %
+ // 12.06 V = 25 %
+ // 11.89 V = 0 %
+ //clusterDataControl.batteryPotential = (11.89 + (0.0077 * batteryLevel.value))
+ clusterDataControl.batteryPotential = batteryLevel.value
+ }
+ Component.onCompleted: clusterDataControl.batteryPotential = batteryLevel.value
+
+ }
+ SlideHolder {
+ id: waterTemperature
+ text: "COOLANT TEMPERATURE"
+ visible: carNumber !== 0
+ min: 40
+ max: 120
+ steps: 8
+ value: 60
+ valueStep: 5
+ enabled: !demoMode.pressed
+ onValueChanged: clusterDataControl.engineTemp = waterTemperature.value
+ Component.onCompleted: clusterDataControl.engineTemp = waterTemperature.value
+ }
+ SlideHolder {
+ id: gasLevel
+ text: "FUEL"
+ visible: carNumber !== 0
+ max: 100
+ steps: 10
+ value: 67
+ onValueChanged: clusterDataControl.gasLevel = gasLevel.value
+ Component.onCompleted: clusterDataControl.gasLevel = gasLevel.value
+ }
+ SlideHolder {
+ id: rpm
+ visible: carNumber !== 0
+ text: "RPM (x1000)"
+ max: 8.0
+ steps: 8
+ value: 4.0
+ valueStep: 0.01
+ enabled: !demoMode.pressed
+ onValueChanged: clusterDataControl.rpm = rpm.value * 1000
+ Component.onCompleted: clusterDataControl.rpm = rpm.value * 1000
+ }
+ }
+ }
+
+ function resetButtonStates() {
+ headLights.pressed = false
+ brakeLights.pressed = false
+ //oilPressureWarning.pressed = false
+ leftFrontDoorButton.pressed = false
+ rightFrontDoorButton.pressed = false
+ leftBackDoorButton.pressed = false
+ rightBackDoorButton.pressed = false
+ bootDoorButton.pressed = false
+ hoodDoorButton.pressed = false
+ tireFailureButton.pressed = false
+ lampFailureButton.pressed = false
+ leftSignalButton.pressed = false
+ rightSignalButton.pressed = false
+ hazardButton.pressed = false
+ gearController.gear = 1
+ gearControllerAutomatic.gear = 1
+ }
+}
diff --git a/CanController/CenterViewOff.png b/CanController/CenterViewOff.png
new file mode 100644
index 0000000..f4b6b62
--- /dev/null
+++ b/CanController/CenterViewOff.png
Binary files differ
diff --git a/CanController/CenterViewOffOpt.png b/CanController/CenterViewOffOpt.png
new file mode 100644
index 0000000..19f2d55
--- /dev/null
+++ b/CanController/CenterViewOffOpt.png
Binary files differ
diff --git a/CanController/CenterViewOn.png b/CanController/CenterViewOn.png
new file mode 100644
index 0000000..eca718f
--- /dev/null
+++ b/CanController/CenterViewOn.png
Binary files differ
diff --git a/CanController/CenterViewOnOpt.png b/CanController/CenterViewOnOpt.png
new file mode 100644
index 0000000..95ca235
--- /dev/null
+++ b/CanController/CenterViewOnOpt.png
Binary files differ
diff --git a/CanController/E-Car_BackDoorLeftOFF.png b/CanController/E-Car_BackDoorLeftOFF.png
new file mode 100644
index 0000000..7ad393a
--- /dev/null
+++ b/CanController/E-Car_BackDoorLeftOFF.png
Binary files differ
diff --git a/CanController/E-Car_BackDoorLeftON.png b/CanController/E-Car_BackDoorLeftON.png
new file mode 100644
index 0000000..096f459
--- /dev/null
+++ b/CanController/E-Car_BackDoorLeftON.png
Binary files differ
diff --git a/CanController/E-Car_BackDoorRightOFF.png b/CanController/E-Car_BackDoorRightOFF.png
new file mode 100644
index 0000000..a0b711b
--- /dev/null
+++ b/CanController/E-Car_BackDoorRightOFF.png
Binary files differ
diff --git a/CanController/E-Car_BackDoorRightON.png b/CanController/E-Car_BackDoorRightON.png
new file mode 100644
index 0000000..52927be
--- /dev/null
+++ b/CanController/E-Car_BackDoorRightON.png
Binary files differ
diff --git a/CanController/E-Car_BrakesOFF.png b/CanController/E-Car_BrakesOFF.png
new file mode 100644
index 0000000..ff98a39
--- /dev/null
+++ b/CanController/E-Car_BrakesOFF.png
Binary files differ
diff --git a/CanController/E-Car_BrakesON.png b/CanController/E-Car_BrakesON.png
new file mode 100644
index 0000000..7518ea6
--- /dev/null
+++ b/CanController/E-Car_BrakesON.png
Binary files differ
diff --git a/CanController/E-Car_FrontDoorLeftOFF.png b/CanController/E-Car_FrontDoorLeftOFF.png
new file mode 100644
index 0000000..7e8f8b8
--- /dev/null
+++ b/CanController/E-Car_FrontDoorLeftOFF.png
Binary files differ
diff --git a/CanController/E-Car_FrontDoorLeftON.png b/CanController/E-Car_FrontDoorLeftON.png
new file mode 100644
index 0000000..18673ba
--- /dev/null
+++ b/CanController/E-Car_FrontDoorLeftON.png
Binary files differ
diff --git a/CanController/E-Car_FrontDoorRightOFF.png b/CanController/E-Car_FrontDoorRightOFF.png
new file mode 100644
index 0000000..ce674c9
--- /dev/null
+++ b/CanController/E-Car_FrontDoorRightOFF.png
Binary files differ
diff --git a/CanController/E-Car_FrontDoorRightON.png b/CanController/E-Car_FrontDoorRightON.png
new file mode 100644
index 0000000..f72ce13
--- /dev/null
+++ b/CanController/E-Car_FrontDoorRightON.png
Binary files differ
diff --git a/CanController/E-Car_HoodOFF.png b/CanController/E-Car_HoodOFF.png
new file mode 100644
index 0000000..908c207
--- /dev/null
+++ b/CanController/E-Car_HoodOFF.png
Binary files differ
diff --git a/CanController/E-Car_HoodON.png b/CanController/E-Car_HoodON.png
new file mode 100644
index 0000000..ccbb2e6
--- /dev/null
+++ b/CanController/E-Car_HoodON.png
Binary files differ
diff --git a/CanController/E-Car_LowBeamsOFF.png b/CanController/E-Car_LowBeamsOFF.png
new file mode 100644
index 0000000..510ed40
--- /dev/null
+++ b/CanController/E-Car_LowBeamsOFF.png
Binary files differ
diff --git a/CanController/E-Car_LowBeamsON.png b/CanController/E-Car_LowBeamsON.png
new file mode 100644
index 0000000..5c23423
--- /dev/null
+++ b/CanController/E-Car_LowBeamsON.png
Binary files differ
diff --git a/CanController/E-Car_Shape.png b/CanController/E-Car_Shape.png
new file mode 100644
index 0000000..a2e49a7
--- /dev/null
+++ b/CanController/E-Car_Shape.png
Binary files differ
diff --git a/CanController/E-Car_TrunkOFF.png b/CanController/E-Car_TrunkOFF.png
new file mode 100644
index 0000000..3aa9082
--- /dev/null
+++ b/CanController/E-Car_TrunkOFF.png
Binary files differ
diff --git a/CanController/E-Car_TrunkON.png b/CanController/E-Car_TrunkON.png
new file mode 100644
index 0000000..1dd8e40
--- /dev/null
+++ b/CanController/E-Car_TrunkON.png
Binary files differ
diff --git a/CanController/E-Car_TurnLeftOFF.png b/CanController/E-Car_TurnLeftOFF.png
new file mode 100644
index 0000000..4496fee
--- /dev/null
+++ b/CanController/E-Car_TurnLeftOFF.png
Binary files differ
diff --git a/CanController/E-Car_TurnLeftON.png b/CanController/E-Car_TurnLeftON.png
new file mode 100644
index 0000000..5535a71
--- /dev/null
+++ b/CanController/E-Car_TurnLeftON.png
Binary files differ
diff --git a/CanController/E-Car_TurnRightOFF.png b/CanController/E-Car_TurnRightOFF.png
new file mode 100644
index 0000000..a0feea1
--- /dev/null
+++ b/CanController/E-Car_TurnRightOFF.png
Binary files differ
diff --git a/CanController/E-Car_TurnRightON.png b/CanController/E-Car_TurnRightON.png
new file mode 100644
index 0000000..5bc7e21
--- /dev/null
+++ b/CanController/E-Car_TurnRightON.png
Binary files differ
diff --git a/CanController/Gear.qml b/CanController/Gear.qml
new file mode 100644
index 0000000..0a3a732
--- /dev/null
+++ b/CanController/Gear.qml
@@ -0,0 +1,455 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: gearMain
+ width: 270
+ height: 270
+ radius: 135
+ color: "#1b1c1d"
+
+ property int gear: 0
+ property int previousGear: 0
+
+ property bool animating: false
+ property alias knobColor: knob.color
+ property color trackColor: "#b6181e"
+ property color unselectecColor: "#ffffff"
+ property color selectecColor: "#1b1c1d"
+
+ onGearChanged: {
+ if (gearMain.animating || gearMain.gear < -1 || gearMain.gear > 5) {
+ gearMain.gear = gearMain.previousGear
+ }
+ else {
+ if (gearMain.previousGear === 0) {
+ if (gearMain.gear === 1) from0to1.start()
+ else if (gearMain.gear === 2) from0to2.start()
+ else if (gearMain.gear === 3) from0to3.start()
+ else if (gearMain.gear === 4) from0to4.start()
+ else if (gearMain.gear === 5) from0to5.start()
+ else if (gearMain.gear === -1) from0toR.start()
+ }
+ else if (gearMain.previousGear === 1) from1to0.start()
+ else if (gearMain.previousGear === 2) from2to0.start()
+ else if (gearMain.previousGear === 3) from3to0.start()
+ else if (gearMain.previousGear === 4) from4to0.start()
+ else if (gearMain.previousGear === 5) from5to0.start()
+ else if (gearMain.previousGear === -1) fromRto0.start()
+ gearMain.previousGear = gearMain.gear
+ }
+ }
+
+ Rectangle {
+ id: verticalLine
+ anchors.centerIn: parent
+ width: 126
+ height: 6
+ color: gearMain.trackColor
+ }
+
+ Rectangle {
+ id: leftHorizontalLine
+ anchors {
+ left: verticalLine.left
+ verticalCenter: parent.verticalCenter
+ }
+ width: 6
+ height: 70
+ color: gearMain.trackColor
+ }
+
+ Rectangle {
+ id: middleHorizontalLine
+ anchors.centerIn: parent
+ width: 6
+ height: 70
+ color: gearMain.trackColor
+ }
+
+ Rectangle {
+ id: rightHorizontalLine
+ anchors {
+ right: verticalLine.right
+ verticalCenter: parent.verticalCenter
+ }
+ width: 6
+ height: 70
+ color: gearMain.trackColor
+ }
+
+ Rectangle {
+ id: knob
+ width: 50
+ height: 50
+ radius: 25
+ color: "#b6181e"
+ property int middleX: 110
+ property int middleY: 110
+ property int leftX: 50
+ property int rightX: 170
+ property int topY: 50
+ property int bottomY: 170
+ x: knob.middleX
+ y: knob.middleY
+
+ SequentialAnimation {
+ id: from0to1
+ PropertyAnimation { target: knob; property: "x"; from: knob.middleX; to: knob.leftX; }
+ PropertyAnimation { target: knob; property: "y"; from: knob.middleY; to: knob.topY; }
+ onRunningChanged: gearMain.animating = from0to1.running;
+ }
+ SequentialAnimation {
+ id: from0to2
+ PropertyAnimation { target: knob; property: "x"; from: knob.middleX; to: knob.leftX; }
+ PropertyAnimation { target: knob; property: "y"; from: knob.middleY; to: knob.bottomY; }
+ onRunningChanged: gearMain.animating = from0to2.running;
+ }
+ PropertyAnimation {
+ id: from0to3
+ target: knob
+ property: "y"
+ from: knob.middleY
+ to: knob.topY
+ onRunningChanged: gearMain.animating = from0to3.running
+ }
+ PropertyAnimation {
+ id: from0to4
+ target: knob
+ property: "y"
+ from: knob.middleY
+ to: knob.bottomY
+ onRunningChanged: gearMain.animating = from0to4.running
+ }
+ SequentialAnimation {
+ id: from0to5
+ PropertyAnimation { target: knob; property: "x"; from: knob.middleX; to: knob.rightX; }
+ PropertyAnimation { target: knob; property: "y"; from: knob.middleY; to: knob.topY; }
+ onRunningChanged: gearMain.animating = from0to5.running
+ }
+ SequentialAnimation {
+ id: from0toR
+ PropertyAnimation { target: knob; property: "x"; from: knob.middleX; to: knob.rightX; }
+ PropertyAnimation { target: knob; property: "y"; from: knob.middleY; to: knob.bottomY; }
+ onRunningChanged: gearMain.animating = from0toR.running
+ }
+ SequentialAnimation {
+ id: from1to0
+ PropertyAnimation { target: knob; property: "y"; from: knob.topY; to: knob.middleY; }
+ PropertyAnimation { target: knob; property: "x"; from: knob.leftX; to: knob.middleX; }
+ onRunningChanged: {
+ if (!from1to0.running) {
+ if (gearMain.gear === 2) from0to2.start()
+ else if (gearMain.gear === 3) from0to3.start()
+ else if (gearMain.gear === 4) from0to4.start()
+ else if (gearMain.gear === 5) from0to5.start()
+ else if (gearMain.gear === -1) from0toR.start()
+ else gearMain.animating = false
+ }
+ else {
+ gearMain.animating = true
+ }
+ }
+ }
+ SequentialAnimation {
+ id: from2to0
+ PropertyAnimation { target: knob; property: "y"; from: knob.bottomY; to: knob.middleY; }
+ PropertyAnimation { target: knob; property: "x"; from: knob.leftX; to: knob.middleX; }
+ onRunningChanged: {
+ if (!from2to0.running) {
+ if (gearMain.gear === 1) from0to1.start()
+ else if (gearMain.gear === 3) from0to3.start()
+ else if (gearMain.gear === 4) from0to4.start()
+ else if (gearMain.gear === 5) from0to5.start()
+ else if (gearMain.gear === -1) from0toR.start()
+ else gearMain.animating = false
+ }
+ else {
+ gearMain.animating = true
+ }
+ }
+ }
+ PropertyAnimation {
+ id: from3to0
+ target: knob
+ property: "y"
+ from: knob.topY
+ to: knob.middleY
+ onRunningChanged: {
+ if (!from3to0.running) {
+ if (gearMain.gear === -1) from0toR.start()
+ else if (gearMain.gear === 1) from0to1.start()
+ else if (gearMain.gear === 2) from0to2.start()
+ else if (gearMain.gear === 4) from0to4.start()
+ else if (gearMain.gear === 5) from0to5.start()
+ else gearMain.animating = false
+ }
+ else {
+ gearMain.animating = true
+ }
+ }
+ }
+ PropertyAnimation {
+ id: from4to0
+ target: knob
+ property: "y"
+ from: knob.bottomY
+ to: knob.middleY
+ onRunningChanged: {
+ if (!from4to0.running) {
+ if (gearMain.gear === 1) from0to1.start()
+ else if (gearMain.gear === 2) from0to2.start()
+ else if (gearMain.gear === 3) from0to3.start()
+ else if (gearMain.gear === 5) from0to5.start()
+ else if (gearMain.gear === -1) from0toR.start()
+ else gearMain.animating = false
+ }
+ else {
+ gearMain.animating = true
+ }
+ }
+ }
+ SequentialAnimation {
+ id: from5to0
+ PropertyAnimation { target: knob; property: "y"; from: knob.topY; to: knob.middleY; }
+ PropertyAnimation { target: knob; property: "x"; from: knob.rightX; to: knob.middleX; }
+ onRunningChanged: {
+ if (!from5to0.running) {
+ if (gearMain.gear === 1) from0to1.start()
+ else if (gearMain.gear === 2) from0to2.start()
+ else if (gearMain.gear === 3) from0to3.start()
+ else if (gearMain.gear === 4) from0to4.start()
+ else if (gearMain.gear === -1) from0toR.start()
+ else gearMain.animating = false
+ }
+ else {
+ gearMain.animating = true
+ }
+ }
+ }
+ SequentialAnimation {
+ id: fromRto0
+ PropertyAnimation { target: knob; property: "y"; from: knob.bottomY; to: knob.middleY; }
+ PropertyAnimation { target: knob; property: "x"; from: knob.rightX; to: knob.middleX; }
+ onRunningChanged: {
+ if (!fromRto0.running) {
+ if (gearMain.gear === 1) from0to1.start()
+ else if (gearMain.gear === 2) from0to2.start()
+ else if (gearMain.gear === 3) from0to3.start()
+ else if (gearMain.gear === 4) from0to4.start()
+ else if (gearMain.gear === 5) from0to5.start()
+ else gearMain.animating = false
+ }
+ else {
+ gearMain.animating = true
+ }
+ }
+ }
+ }
+
+ Item {
+ anchors {
+ bottom: leftHorizontalLine.top
+ horizontalCenter: leftHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: text1
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "1"
+ color: (!gearMain.animating && gearMain.gear === 1 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+
+ Item {
+ anchors {
+ top: leftHorizontalLine.bottom
+ horizontalCenter: leftHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: text2
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "2"
+ color: (!gearMain.animating && gearMain.gear === 2 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+ Item {
+ anchors {
+ bottom: middleHorizontalLine.top
+ horizontalCenter: middleHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: text3
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "3"
+ color: (!gearMain.animating && gearMain.gear === 3 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+ Item {
+ anchors {
+ top: middleHorizontalLine.bottom
+ horizontalCenter: middleHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: text4
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "4"
+ color: (!gearMain.animating && gearMain.gear === 4 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+ Item {
+ anchors {
+ bottom: rightHorizontalLine.top
+ horizontalCenter: rightHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: text5
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "5"
+ color: (!gearMain.animating && gearMain.gear === 5 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+ Item {
+ anchors {
+ top: rightHorizontalLine.bottom
+ horizontalCenter: rightHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: textR
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "R"
+ color: (!gearMain.animating && gearMain.gear === -1 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: 32
+ height: 32
+ radius: 16
+ color: gearMain.trackColor
+ Rectangle {
+ anchors.centerIn: parent
+ width: 28
+ height: 28
+ radius: 14
+ color: (!gearMain.animating && gearMain.gear === 0 ? gearMain.unselectecColor
+ : gearMain.selectecColor)
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 20
+ text: "N"
+ color: (!gearMain.animating && gearMain.gear === 0 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+ }
+
+ MouseArea {
+ x: 0
+ y: 0
+ width: 105
+ height: 135
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 1
+ }
+ MouseArea {
+ x: 105
+ y: 0
+ width: 60
+ height: 105
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 3
+ }
+ MouseArea {
+ x: 165
+ y: 0
+ width: 105
+ height: 135
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 5
+ }
+ MouseArea {
+ x: 0
+ y: 135
+ width: 105
+ height: 135
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 2
+ }
+ MouseArea {
+ x: 105
+ y: 165
+ width: 60
+ height: 105
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 4
+ }
+ MouseArea {
+ x: 165
+ y: 135
+ width: 105
+ height: 135
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = -1
+ }
+ MouseArea {
+ x: 105
+ y: 105
+ width: 60
+ height: 60
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 0
+ }
+
+}
diff --git a/CanController/GearAutomatic.qml b/CanController/GearAutomatic.qml
new file mode 100644
index 0000000..70b6ea1
--- /dev/null
+++ b/CanController/GearAutomatic.qml
@@ -0,0 +1,236 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: gearMain
+ width: 270
+ height: 270
+ radius: 135
+ color: "#1b1c1d"
+
+ property int gear: 0
+ property int previousGear: 0
+
+ property bool animating: false
+ property alias knobColor: knob.color
+ property color trackColor: "#b6181e"
+ property color unselectecColor: "#ffffff"
+ property color selectecColor: "#1b1c1d"
+
+ onGearChanged: {
+ if (gearMain.animating || gearMain.gear < -1 || gearMain.gear > 1) {
+ gearMain.gear = gearMain.previousGear
+ } else {
+ if (gearMain.previousGear === 0) {
+ if (gearMain.gear === 1)
+ from0to1.start()
+ else if (gearMain.gear === -1)
+ from0toR.start()
+ } else if (gearMain.previousGear === 1) {
+ from1to0.start()
+ } else if (gearMain.previousGear === -1) {
+ fromRto0.start()
+ }
+ gearMain.previousGear = gearMain.gear
+ }
+ }
+
+ Rectangle {
+ id: verticalLine
+ anchors.centerIn: parent
+ width: 126
+ height: 6
+ color: gearMain.trackColor
+ }
+
+ Rectangle {
+ id: leftHorizontalLine
+ anchors {
+ left: verticalLine.left
+ bottom: parent.verticalCenter
+ }
+ width: 6
+ height: 35
+ color: gearMain.trackColor
+ }
+
+ Rectangle {
+ id: rightHorizontalLine
+ anchors {
+ right: verticalLine.right
+ top: parent.verticalCenter
+ }
+ width: 6
+ height: 35
+ color: gearMain.trackColor
+ }
+
+ Rectangle {
+ id: knob
+ width: 50
+ height: 50
+ radius: 25
+ color: "#b6181e"
+ property int middleX: 110
+ property int middleY: 110
+ property int leftX: 50
+ property int rightX: 170
+ property int topY: 50
+ property int bottomY: 170
+ x: knob.middleX
+ y: knob.middleY
+
+ SequentialAnimation {
+ id: from0to1
+ PropertyAnimation { target: knob; property: "x"; from: knob.middleX; to: knob.leftX; }
+ PropertyAnimation { target: knob; property: "y"; from: knob.middleY; to: knob.topY; }
+ onRunningChanged: gearMain.animating = from0to1.running
+ }
+ SequentialAnimation {
+ id: from0toR
+ PropertyAnimation { target: knob; property: "x"; from: knob.middleX; to: knob.rightX; }
+ PropertyAnimation { target: knob; property: "y"; from: knob.middleY; to: knob.bottomY; }
+ onRunningChanged: gearMain.animating = from0toR.running
+ }
+ SequentialAnimation {
+ id: from1to0
+ PropertyAnimation { target: knob; property: "y"; from: knob.topY; to: knob.middleY; }
+ PropertyAnimation { target: knob; property: "x"; from: knob.leftX; to: knob.middleX; }
+ onRunningChanged: {
+ if (!from1to0.running) {
+ if (gearMain.gear === -1)
+ from0toR.start()
+ else
+ gearMain.animating = false
+ } else {
+ gearMain.animating = true
+ }
+ }
+ }
+ SequentialAnimation {
+ id: fromRto0
+ PropertyAnimation { target: knob; property: "y"; from: knob.bottomY; to: knob.middleY; }
+ PropertyAnimation { target: knob; property: "x"; from: knob.rightX; to: knob.middleX; }
+ onRunningChanged: {
+ if (!fromRto0.running) {
+ if (gearMain.gear === 1)
+ from0to1.start()
+ else
+ gearMain.animating = false
+ } else {
+ gearMain.animating = true
+ }
+ }
+ }
+ }
+
+ Item {
+ anchors {
+ bottom: leftHorizontalLine.top
+ horizontalCenter: leftHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: text1
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "D"
+ color: (!gearMain.animating && gearMain.gear === 1 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+
+ Item {
+ anchors {
+ top: rightHorizontalLine.bottom
+ horizontalCenter: rightHorizontalLine.horizontalCenter
+ }
+ width: 50
+ height: 50
+ Text {
+ id: textR
+ anchors.centerIn: parent
+ font.pixelSize: 30
+ text: "R"
+ color: (!gearMain.animating && gearMain.gear === -1 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: 32
+ height: 32
+ radius: 16
+ color: gearMain.trackColor
+ Rectangle {
+ anchors.centerIn: parent
+ width: 28
+ height: 28
+ radius: 14
+ color: (!gearMain.animating && gearMain.gear === 0 ? gearMain.unselectecColor
+ : gearMain.selectecColor)
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 20
+ text: "N"
+ color: (!gearMain.animating && gearMain.gear === 0 ? gearMain.selectecColor
+ : gearMain.unselectecColor)
+ }
+ }
+ }
+
+ MouseArea {
+ x: 0
+ y: 0
+ width: 105
+ height: 135
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 1
+ }
+ MouseArea {
+ x: 165
+ y: 135
+ width: 105
+ height: 135
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = -1
+ }
+ MouseArea {
+ x: 105
+ y: 105
+ width: 60
+ height: 60
+ enabled: !gearMain.animating
+ onClicked: gearMain.gear = 0
+ }
+
+}
diff --git a/CanController/Icon_BulbFailure_OFF.png b/CanController/Icon_BulbFailure_OFF.png
new file mode 100644
index 0000000..1ff0fef
--- /dev/null
+++ b/CanController/Icon_BulbFailure_OFF.png
Binary files differ
diff --git a/CanController/Icon_BulbFailure_ON.png b/CanController/Icon_BulbFailure_ON.png
new file mode 100644
index 0000000..cd083cd
--- /dev/null
+++ b/CanController/Icon_BulbFailure_ON.png
Binary files differ
diff --git a/CanController/Icon_HazardWarning_OFF.png b/CanController/Icon_HazardWarning_OFF.png
new file mode 100644
index 0000000..88477d2
--- /dev/null
+++ b/CanController/Icon_HazardWarning_OFF.png
Binary files differ
diff --git a/CanController/Icon_HazardWarning_ON.png b/CanController/Icon_HazardWarning_ON.png
new file mode 100644
index 0000000..95e5dab
--- /dev/null
+++ b/CanController/Icon_HazardWarning_ON.png
Binary files differ
diff --git a/CanController/Icon_LowBeam_OFF.png b/CanController/Icon_LowBeam_OFF.png
new file mode 100644
index 0000000..411682a
--- /dev/null
+++ b/CanController/Icon_LowBeam_OFF.png
Binary files differ
diff --git a/CanController/Icon_LowBeam_ON.png b/CanController/Icon_LowBeam_ON.png
new file mode 100644
index 0000000..d5e9188
--- /dev/null
+++ b/CanController/Icon_LowBeam_ON.png
Binary files differ
diff --git a/CanController/Icon_ParkingBrake_OFF.png b/CanController/Icon_ParkingBrake_OFF.png
new file mode 100644
index 0000000..6819d87
--- /dev/null
+++ b/CanController/Icon_ParkingBrake_OFF.png
Binary files differ
diff --git a/CanController/Icon_ParkingBrake_ON.png b/CanController/Icon_ParkingBrake_ON.png
new file mode 100644
index 0000000..dfe7ab5
--- /dev/null
+++ b/CanController/Icon_ParkingBrake_ON.png
Binary files differ
diff --git a/CanController/Icon_TurnLeft_OFF.png b/CanController/Icon_TurnLeft_OFF.png
new file mode 100644
index 0000000..eb19b74
--- /dev/null
+++ b/CanController/Icon_TurnLeft_OFF.png
Binary files differ
diff --git a/CanController/Icon_TurnLeft_ON.png b/CanController/Icon_TurnLeft_ON.png
new file mode 100644
index 0000000..8a47ee6
--- /dev/null
+++ b/CanController/Icon_TurnLeft_ON.png
Binary files differ
diff --git a/CanController/Icon_TurnRight_OFF.png b/CanController/Icon_TurnRight_OFF.png
new file mode 100644
index 0000000..5ba8141
--- /dev/null
+++ b/CanController/Icon_TurnRight_OFF.png
Binary files differ
diff --git a/CanController/Icon_TurnRight_ON.png b/CanController/Icon_TurnRight_ON.png
new file mode 100644
index 0000000..9803e1a
--- /dev/null
+++ b/CanController/Icon_TurnRight_ON.png
Binary files differ
diff --git a/CanController/Icon_TyreMalfunction_OFF.png b/CanController/Icon_TyreMalfunction_OFF.png
new file mode 100644
index 0000000..90dbf9a
--- /dev/null
+++ b/CanController/Icon_TyreMalfunction_OFF.png
Binary files differ
diff --git a/CanController/Icon_TyreMalfunction_ON.png b/CanController/Icon_TyreMalfunction_ON.png
new file mode 100644
index 0000000..59459cb
--- /dev/null
+++ b/CanController/Icon_TyreMalfunction_ON.png
Binary files differ
diff --git a/CanController/S-Car_BrakesOFF.png b/CanController/S-Car_BrakesOFF.png
new file mode 100644
index 0000000..c485aae
--- /dev/null
+++ b/CanController/S-Car_BrakesOFF.png
Binary files differ
diff --git a/CanController/S-Car_BrakesON.png b/CanController/S-Car_BrakesON.png
new file mode 100644
index 0000000..bdb3198
--- /dev/null
+++ b/CanController/S-Car_BrakesON.png
Binary files differ
diff --git a/CanController/S-Car_DoorLeftOFF.png b/CanController/S-Car_DoorLeftOFF.png
new file mode 100644
index 0000000..1c29d02
--- /dev/null
+++ b/CanController/S-Car_DoorLeftOFF.png
Binary files differ
diff --git a/CanController/S-Car_DoorLeftON.png b/CanController/S-Car_DoorLeftON.png
new file mode 100644
index 0000000..d2c66cb
--- /dev/null
+++ b/CanController/S-Car_DoorLeftON.png
Binary files differ
diff --git a/CanController/S-Car_DoorRightOFF.png b/CanController/S-Car_DoorRightOFF.png
new file mode 100644
index 0000000..3da124e
--- /dev/null
+++ b/CanController/S-Car_DoorRightOFF.png
Binary files differ
diff --git a/CanController/S-Car_DoorRightON.png b/CanController/S-Car_DoorRightON.png
new file mode 100644
index 0000000..43488a7
--- /dev/null
+++ b/CanController/S-Car_DoorRightON.png
Binary files differ
diff --git a/CanController/S-Car_HoodOFF.png b/CanController/S-Car_HoodOFF.png
new file mode 100644
index 0000000..3b768a0
--- /dev/null
+++ b/CanController/S-Car_HoodOFF.png
Binary files differ
diff --git a/CanController/S-Car_HoodON.png b/CanController/S-Car_HoodON.png
new file mode 100644
index 0000000..307bd56
--- /dev/null
+++ b/CanController/S-Car_HoodON.png
Binary files differ
diff --git a/CanController/S-Car_LowBeamsOFF.png b/CanController/S-Car_LowBeamsOFF.png
new file mode 100644
index 0000000..4391898
--- /dev/null
+++ b/CanController/S-Car_LowBeamsOFF.png
Binary files differ
diff --git a/CanController/S-Car_LowBeamsON.png b/CanController/S-Car_LowBeamsON.png
new file mode 100644
index 0000000..8873915
--- /dev/null
+++ b/CanController/S-Car_LowBeamsON.png
Binary files differ
diff --git a/CanController/S-Car_Shape.png b/CanController/S-Car_Shape.png
new file mode 100644
index 0000000..a17a926
--- /dev/null
+++ b/CanController/S-Car_Shape.png
Binary files differ
diff --git a/CanController/S-Car_TrunkOFF.png b/CanController/S-Car_TrunkOFF.png
new file mode 100644
index 0000000..dd05e39
--- /dev/null
+++ b/CanController/S-Car_TrunkOFF.png
Binary files differ
diff --git a/CanController/S-Car_TrunkON.png b/CanController/S-Car_TrunkON.png
new file mode 100644
index 0000000..e7c4ecc
--- /dev/null
+++ b/CanController/S-Car_TrunkON.png
Binary files differ
diff --git a/CanController/S-Car_TurnLeftOFF.png b/CanController/S-Car_TurnLeftOFF.png
new file mode 100644
index 0000000..8f2ae29
--- /dev/null
+++ b/CanController/S-Car_TurnLeftOFF.png
Binary files differ
diff --git a/CanController/S-Car_TurnLeftON.png b/CanController/S-Car_TurnLeftON.png
new file mode 100644
index 0000000..b3fa4cc
--- /dev/null
+++ b/CanController/S-Car_TurnLeftON.png
Binary files differ
diff --git a/CanController/S-Car_TurnRightOFF.png b/CanController/S-Car_TurnRightOFF.png
new file mode 100644
index 0000000..b6610d7
--- /dev/null
+++ b/CanController/S-Car_TurnRightOFF.png
Binary files differ
diff --git a/CanController/S-Car_TurnRightON.png b/CanController/S-Car_TurnRightON.png
new file mode 100644
index 0000000..e009bc2
--- /dev/null
+++ b/CanController/S-Car_TurnRightON.png
Binary files differ
diff --git a/CanController/Slide.qml b/CanController/Slide.qml
new file mode 100644
index 0000000..e23a018
--- /dev/null
+++ b/CanController/Slide.qml
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+import QtQuick 2.0
+
+Item {
+ id: mainSlide
+ width: 500
+ height: 80
+
+ property real min: 0
+ property real value: min
+ property real max: 100
+ property int steps: 10
+ property real valueStep: 5
+ property color sliderColor: enabled ? "#b6181e" : "lightGray"
+
+ Rectangle {
+ id: slideRail
+ anchors {
+ top: parent.top
+ topMargin: 40
+ left: parent.left
+ leftMargin: 5
+ right: parent.right
+ rightMargin: 5
+ }
+ height: 4
+ color: "#d6d6d6"
+ property int railStep: ((mainSlide.max - mainSlide.min) / mainSlide.steps)
+ Repeater {
+ model: (mainSlide.steps + 1)
+ anchors.bottom: parent.bottom
+ Item {
+ x: index * width - 0.5 * width
+ y: -6
+ width: (slideRail.width / mainSlide.steps)
+ height: 30
+ Rectangle {
+ id: slideIndex
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 3
+ height: 10
+ //radius: 3
+ color: (mainSlide.value >= (mainSlide.min + (index * slideRail.railStep))
+ ? sliderColor : "#d6d6d6")
+ }
+ Text {
+ anchors {
+ bottom: slideIndex.bottom
+ bottomMargin: 25
+ horizontalCenter: parent.horizontalCenter
+ }
+ color: (mainSlide.value >= (mainSlide.min + (index * slideRail.railStep))
+ ? sliderColor : "#d6d6d6")
+ font.pixelSize: 12
+ text: mainSlide.min + (index * slideRail.railStep)
+ }
+ }
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ slideMouse.changeX = true
+ if (mouse.x <= slideRail.x)
+ hiddenSlider.x = (slideRail.x - (0.5 * hiddenSlider.width))
+ else if (mouse.x >= slideRail.x + slideRail.width)
+ hiddenSlider.x = (slideRail.x + slideRail.width - (0.5 * hiddenSlider.width))
+ else
+ hiddenSlider.x = (mouse.x - (0.5 * hiddenSlider.width))
+ slideMouse.changeX = false
+ }
+ }
+ Rectangle {
+ id: slideValue
+ anchors {
+ top: slideRail.top
+ left: slideRail.left
+ right: slider.right
+ rightMargin: 1
+ }
+ radius: 5
+ height: 4
+ color: sliderColor
+ }
+
+ function calculateSliderPosition() {
+ slider.x = (slideRail.x - (0.5 * slider.width)
+ + (((Math.min(Math.max(mainSlide.value, mainSlide.min), mainSlide.max)
+ - mainSlide.min) / (mainSlide.max - mainSlide.min)) * slideRail.width))
+ }
+
+ onValueChanged: {
+ mainSlide.calculateSliderPosition()
+ }
+
+ Item {
+ id: hiddenSlider
+ width: 60
+ height: parent.height
+ onXChanged: {
+ var tempValue = (mainSlide.min + (((hiddenSlider.x - slideRail.x
+ + (0.5 * hiddenSlider.width)) / slideRail.width)
+ * (mainSlide.max - mainSlide.min)))
+ var tempStep = (tempValue % mainSlide.valueStep)
+ mainSlide.value = tempValue - tempStep
+ + (tempStep < (0.5 * mainSlide.valueStep) ? 0 : mainSlide.valueStep)
+ }
+ MouseArea {
+ id: slideMouse
+ anchors.fill: parent
+ property bool changeX: false
+ drag {
+ target: hiddenSlider
+ axis: Drag.XAxis
+ minimumX : (slideRail.x - (0.5 * hiddenSlider.width))
+ maximumX: (slideRail.x + slideRail.width - (0.5 * hiddenSlider.width))
+ onActiveChanged: slideMouse.changeX = slideMouse.drag.active
+ }
+ }
+ }
+
+ Rectangle {
+ id: slider
+ Component.onCompleted: mainSlide.calculateSliderPosition()
+ anchors {
+ top: parent.top
+ topMargin: 22
+ }
+
+ width: 16
+ height: 40
+ radius: 8
+ color: sliderColor
+ }
+}
diff --git a/CanController/SlideHolder.qml b/CanController/SlideHolder.qml
new file mode 100644
index 0000000..394122e
--- /dev/null
+++ b/CanController/SlideHolder.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ width: parent.width
+ height: (0.25 * parent.height)
+ property alias text: sliderText.text
+ property alias max: slide.max
+ property alias min: slide.min
+ property alias steps: slide.steps
+ property alias value: slide.value
+ property alias valueStep: slide.valueStep
+
+ Text {
+ id: sliderText
+ anchors {
+ top: parent.top
+ topMargin: 10
+ left: parent.left
+ leftMargin: 5
+ }
+ font.pixelSize: 14
+ }
+
+ Slide {
+ id: slide
+ anchors{
+ top: sliderText.bottom
+ left: parent.left
+ right: parent.right
+ }
+ }
+}
diff --git a/CanController/ViewChange.qml b/CanController/ViewChange.qml
new file mode 100644
index 0000000..3dd38d0
--- /dev/null
+++ b/CanController/ViewChange.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle{
+ id: viewButton
+ height: 60
+ radius: 5
+ border.width: 2
+ color: pressed ? blinkColor : "white"
+
+ property alias text: buttonText.text
+ property bool mainView: true
+ property bool pressed: false
+ property bool optionalIcons: false
+
+ property color blinkColor: "#26282a"
+ property color textBlinkColor: "#d6d6d6"
+
+ property url iconOn: optionalIcons ? "qrc:/CenterViewOnOpt.png" : "qrc:/CenterViewOn.png"
+ property url iconOff: optionalIcons ? "qrc:/CenterViewOffOpt.png" : "qrc:/CenterViewOff.png"
+
+ onPressedChanged: {
+ // TODO: Hack, use oilTemp/oilPressure CAN messages for view change
+ if (mainView)
+ clusterDataControl.oilTemp = pressed ? 10 : 0
+ else
+ clusterDataControl.oilPressure = pressed ? 10 : 0
+ }
+
+ MouseArea {
+ id: buttonMouse
+ anchors.fill: parent
+ onPressed: {
+ buttonText.color = textBlinkColor
+ viewButton.pressed = !viewButton.pressed
+ }
+ onReleased: {
+ buttonText.color = blinkColor
+ viewButton.pressed = !viewButton.pressed
+ }
+ }
+
+ Column {
+ spacing: 10
+
+ anchors.centerIn: parent
+ Image {
+ source: viewButton.pressed ? iconOff : iconOn
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ Text {
+ id: buttonText
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pixelSize: 14
+ color: "#26282a"
+ }
+ }
+}
diff --git a/CanController/canclusterdatacontrol.cpp b/CanController/canclusterdatacontrol.cpp
new file mode 100644
index 0000000..4b2ff5f
--- /dev/null
+++ b/CanController/canclusterdatacontrol.cpp
@@ -0,0 +1,934 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "canclusterdatacontrol.h"
+
+#include <QCanBus>
+#include <QtGlobal>
+#include <QDateTime>
+
+#include <QDebug>
+
+#define SOCKETCAN "socketcan"
+
+// J1939 PGNs
+#define PGN_65268 0xFEF4 // Tire Condition - TIRE
+#define PGN_64933 0xFDA5 // Door Control 2 - DC2
+#define PGN_64972 0xFDCC // Light Control
+#define PGN_61445 0xF005 // Electronic Transmission Controller 2 - ETC2
+#define PGN_65265 0xFEF1 // Cruise Control/Vehicle Speed - CCVS
+#define PGN_65267 0xFEF3 // vehicle position - VP
+#define PGN_65256 0xFEE8 // vehicle direction/speed
+#define PGN_65262 0xFEEE // Engine Temperature 1 - ET1
+#define PGN_65263 0xFEEF // Engine Fluid Level/Pressure 1 - EFL/P1
+#define PGN_65271 0xFEF7 // Vehicle Electrical Power - VEP
+#define PGN_65276 0xFEFC // Dash Display - DD
+#define PGN_61444 0xF004 // Electronic Engine Controller 1 - EEC1
+#define PGN_60928 0xEE00 // Address Calimed - ACL
+
+// door defines
+#define DOOR_INIT 0xF33CCFF1FCFFFF0F
+#define OPEN_DOOR_1 0x400000000000000
+#define OPEN_DOOR_2 0x1000000000000
+#define OPEN_DOOR_3 0x40000000000000
+#define OPEN_DOOR_4 0x100000000000
+#define OPEN_DOOR_5 0x400000000
+#define OPEN_DOOR_6 0x1000000
+
+// light defines
+#define LIGHT_INIT 0xF000FFFFFFFFFFFF
+#define HEAD_LIGHT 0x200000000000000
+#define PARK_LIGHT 0x100000000000000
+#define LIGHT_ERROR 0x400000000000000
+#define LEFT_TURN_SIGNAL 0x10000000000000
+#define RIGHT_TURN_SIGNAL 0x20000000000000
+#define HAZARD_SIGNAL 0x4000000000000
+
+// Current gear
+#define GEAR_PARK 0xFB
+#define GEAR_REVERSE 0x7C
+#define GEAR_NEUTRAL 0x7D
+// #define GEAR_1 0x7E
+// #define GEAR_2 0x7F
+// #define GEAR_3 0x80
+// #define GEAR_4 0x81
+// #define GEAR_5 0x82
+// #define GEAR_6 0x83
+
+//#define _CAN_DEBUG
+
+CanClusterDataControl::CanClusterDataControl(QObject* parent) :
+ ClusterDataControlInterface(parent),
+ m_canBus(QCanBus::instance()),
+ m_device(Q_NULLPTR),
+ m_doorStatus(DOOR_INIT),
+ m_lightStatus(LIGHT_INIT),
+ m_brake(false)
+{
+ Q_ASSERT(m_canBus);
+ qsrand(QDateTime::currentMSecsSinceEpoch());
+ QStringList plugins(m_canBus->plugins());
+ if (plugins.contains(SOCKETCAN)) {
+ m_device = m_canBus->createDevice(SOCKETCAN, "can0");
+ m_device->setParent(this);
+ connect(m_device, SIGNAL(errorOccurred(QCanBusDevice::CanBusError)), this, SLOT(canError(QCanBusDevice::CanBusError)));
+ connect(m_device, SIGNAL(framesReceived()), this, SLOT(canFramesReceived()));
+ connect(m_device, SIGNAL(stateChanged(QCanBusDevice::CanBusDeviceState)), this, SLOT(canStateChanged(QCanBusDevice::CanBusDeviceState)));
+#ifdef _CAN_DEBUG
+ connect(m_device, SIGNAL(framesWritten(qint64)), this, SLOT(canFramesWritten(qint64)));
+ qDebug() << "CanClusterDataControl::CanClusterDataControl - connect device:" <<
+#endif
+ m_device->connectDevice();
+ }
+}
+
+int CanClusterDataControl::carId() const
+{
+ return m_carId;
+}
+
+bool CanClusterDataControl::headLight() const
+{
+ return (m_lightStatus & HEAD_LIGHT);
+}
+
+bool CanClusterDataControl::parkLight() const
+{
+ return (m_lightStatus & PARK_LIGHT);
+}
+
+bool CanClusterDataControl::rightTurnLight() const
+{
+ return (m_lightStatus & RIGHT_TURN_SIGNAL);
+}
+
+bool CanClusterDataControl::leftTurnLight() const
+{
+ return (m_lightStatus & LEFT_TURN_SIGNAL);
+}
+
+int CanClusterDataControl::gear() const
+{
+ return m_gear;
+}
+
+bool CanClusterDataControl::lightFailure() const
+{
+ return (m_lightStatus & LIGHT_ERROR);
+}
+
+bool CanClusterDataControl::frontLeftDoorOpen() const
+{
+ return (m_doorStatus & OPEN_DOOR_1);
+}
+
+bool CanClusterDataControl::frontRightDoorOpen() const
+{
+ return (m_doorStatus & OPEN_DOOR_2);
+}
+
+bool CanClusterDataControl::rearLeftDoorOpen() const
+{
+ return (m_doorStatus & OPEN_DOOR_3);
+}
+
+bool CanClusterDataControl::rearRightDoorOpen() const
+{
+ return (m_doorStatus & OPEN_DOOR_4);
+}
+
+bool CanClusterDataControl::trunkOpen() const
+{
+ return (m_doorStatus & OPEN_DOOR_5);
+}
+
+bool CanClusterDataControl::hoodOpen() const
+{
+ return (m_doorStatus & OPEN_DOOR_6);
+}
+
+bool CanClusterDataControl::flatTire() const
+{
+ return m_flatTire;
+}
+
+double CanClusterDataControl::direction() const
+{
+ return m_direction;
+}
+
+double CanClusterDataControl::longitude() const
+{
+ return m_longitude;
+}
+
+double CanClusterDataControl::latitude() const
+{
+ return m_latitude;
+}
+
+double CanClusterDataControl::vehicleSpeed() const
+{
+ return m_vehicleSpeed;
+}
+
+bool CanClusterDataControl::hazardSignal() const
+{
+ return (m_lightStatus & HAZARD_SIGNAL);
+}
+
+bool CanClusterDataControl::brake() const
+{
+ return m_brake;
+}
+
+double CanClusterDataControl::oilTemp() const
+{
+ return m_oilTemp;
+}
+
+int CanClusterDataControl::oilPressure() const
+{
+ return m_oilPressure;
+}
+
+double CanClusterDataControl::batteryPotential() const
+{
+ return m_batteryPotential;
+}
+
+double CanClusterDataControl::gasLevel() const
+{
+ return m_gasLevel;
+}
+
+int CanClusterDataControl::rpm() const
+{
+ return m_rpm;
+}
+
+int CanClusterDataControl::engineTemp() const
+{
+ return m_engineTemp;
+}
+
+void CanClusterDataControl::setVehicleSpeed(double vehicleSpeed)
+{
+ if (m_vehicleSpeed == vehicleSpeed)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setVehicleSpeed: %f", vehicleSpeed);
+#endif
+
+ m_vehicleSpeed = vehicleSpeed;
+
+ sendCCVS();
+
+ emit vehicleSpeedChanged(vehicleSpeed);
+}
+
+void CanClusterDataControl::setLatitude(double latitude)
+{
+ if (m_latitude == latitude)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setLatitude: %f", latitude);
+#endif
+
+ m_latitude = latitude;
+ emit latitudeChanged(latitude);
+}
+
+void CanClusterDataControl::setLongitude(double longitude)
+{
+ if (m_longitude == longitude)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setLongitude: %f", longitude);
+#endif
+
+ m_longitude = longitude;
+ emit longitudeChanged(longitude);
+}
+
+void CanClusterDataControl::setDirection(double direction)
+{
+ if (m_direction == direction)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setDirection: %f", direction);
+#endif
+
+ quint16 convertedDirection(128.0 * direction); // 1/128 deg/bit
+ QByteArray directionData;
+ directionData.append((convertedDirection >> 8) & 0xff);
+ directionData.append(convertedDirection & 0xff);
+ char emptyData[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+ directionData.append(emptyData, 6);
+
+ QCanBusFrame directionFrame(PGN_65256, directionData);
+
+ if (!m_device->writeFrame(directionFrame)) {
+ qWarning("CanClusterDataControl::setDirection - Error in pgn 65256 - vehicle direction/speed - VDS: %s", qPrintable(m_device->errorString()));
+ return;
+ }
+
+ m_direction = direction;
+ emit directionChanged(direction);
+}
+
+void CanClusterDataControl::setFlatTire(bool flatTire)
+{
+ if (m_flatTire == flatTire)
+ return;
+
+ m_flatTire = flatTire;
+
+ char tireId(0x00); // front left
+ // tireId = 0x01; // front right
+ // tireId = 0x10; // back left
+ // tireId = 0x11; // back right
+
+ // status 2 bits:
+ // 00 Ok (no fault)
+ // 01 Tire leak detected
+ // 10 Error
+ // 11 Not Supported
+
+ // temperature, Resolution: 0.03125 deg C/bit, -273 deg C offset
+ // spn242 - Tire Temperature - Temperature at the surface of the tire sidewall.
+ // Data Length: 2 bytes
+ // Resolution: 0.03125 deg C/bit , -273 deg C offset
+ // Data Range: -273 to 1735 deg C
+ quint16 temperature(0x1dc0 + (qrand() % 0x960)); // -35 to +40 C
+
+ if (flatTire) {
+ // pressure: 0 kPa
+ // status: 01 Tire leak detected
+ sendTireConditionData(tireId, 0x0, temperature, 0x01);
+ }
+ else {
+ char pressure(0x31 + (qrand() % 0xf)); // 196 - 256 kPa
+ // status: 00 Ok (no fault)
+ sendTireConditionData(tireId, pressure, temperature, 0x00);
+ }
+
+ emit flatTireChanged(flatTire);
+}
+
+void CanClusterDataControl::setFrontLeftDoorOpen(bool doorOpen)
+{
+ if ((m_doorStatus & OPEN_DOOR_1) == doorOpen)
+ return;
+
+ sendDoorOpenStatus(OPEN_DOOR_1, doorOpen);
+
+ emit frontLeftDoorOpenChanged(doorOpen);
+}
+
+void CanClusterDataControl::setFrontRightDoorOpen(bool doorOpen)
+{
+ if ((m_doorStatus & OPEN_DOOR_2) == doorOpen)
+ return;
+
+ sendDoorOpenStatus(OPEN_DOOR_2, doorOpen);
+
+ emit frontRightDoorOpenChanged(doorOpen);
+}
+
+void CanClusterDataControl::setRearLeftDoorOpen(bool doorOpen)
+{
+ if ((m_doorStatus & OPEN_DOOR_3) == doorOpen)
+ return;
+
+ sendDoorOpenStatus(OPEN_DOOR_3, doorOpen);
+
+ emit rearLeftDoorOpenChanged(doorOpen);
+}
+
+void CanClusterDataControl::setRearRightDoorOpen(bool doorOpen)
+{
+ if ((m_doorStatus & OPEN_DOOR_4) == doorOpen)
+ return;
+
+ sendDoorOpenStatus(OPEN_DOOR_4, doorOpen);
+
+ emit rearRightDoorOpenChanged(doorOpen);
+}
+
+void CanClusterDataControl::setTrunkOpen(bool doorOpen)
+{
+ if ((m_doorStatus & OPEN_DOOR_5) == doorOpen)
+ return;
+
+ sendDoorOpenStatus(OPEN_DOOR_5, doorOpen);
+
+ emit trunkOpenChanged(doorOpen);
+}
+
+void CanClusterDataControl::setHoodOpen(bool doorOpen)
+{
+ if ((m_doorStatus & OPEN_DOOR_6) == doorOpen)
+ return;
+
+ sendDoorOpenStatus(OPEN_DOOR_6, doorOpen);
+
+ emit hoodOpenChanged(doorOpen);
+}
+
+void CanClusterDataControl::setLightFailure(bool lightFailure)
+{
+ if ((m_lightStatus & LIGHT_ERROR) == lightFailure)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setLightFailure - status: %s", (lightFailure ? "on" : "off"));
+#endif
+
+ sendLightStatus(LIGHT_ERROR, lightFailure);
+ emit lightFailureChanged(lightFailure);
+}
+
+void CanClusterDataControl::setGear(int gear)
+{
+ if (m_gear == gear)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setGear: %d", gear);
+#endif
+
+ m_gear = gear;
+
+ char driveGear;
+ if (gear == 0xff ) {
+ driveGear = GEAR_PARK;
+ }
+ else if (gear < 0) {
+ driveGear = GEAR_REVERSE;
+ }
+ else {
+ driveGear = (GEAR_NEUTRAL + gear);
+ }
+
+ QByteArray gearData;
+ char emptyData[3] = { 0x0, 0x0, 0x0 };
+ gearData.append(emptyData, 3);
+ gearData.append(driveGear);
+ char emptyData2[4] = { 0x0, 0x0, 0x0, 0x0 };
+ gearData.append(emptyData2, 4);
+ QCanBusFrame gearFrame(PGN_61445, gearData);
+ if (!m_device->writeFrame(gearFrame)) {
+ qWarning("CanClusterDataControl::setGear - Error in pgn 61445 - Electronic Transmission Controller 2 - ETC2 send: %s", qPrintable(m_device->errorString()));
+ }
+
+ emit gearChanged(gear);
+}
+
+void CanClusterDataControl::setLeftTurnLight(bool leftTurnLight)
+{
+ if ((m_lightStatus & HAZARD_SIGNAL) || (m_lightStatus & LEFT_TURN_SIGNAL) == leftTurnLight)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setLeftTurnLight - status: %s", (leftTurnLight ? "on" : "off"));
+#endif
+
+ sendLightStatus(LEFT_TURN_SIGNAL, leftTurnLight);
+ emit leftTurnLightChanged(leftTurnLight);
+}
+
+void CanClusterDataControl::setRightTurnLight(bool rightTurnLight)
+{
+ if ((m_lightStatus & HAZARD_SIGNAL) || (m_lightStatus & RIGHT_TURN_SIGNAL) == rightTurnLight)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setRightTurnLight - status: %s", (rightTurnLight ? "on" : "off"));
+#endif
+
+ sendLightStatus(RIGHT_TURN_SIGNAL, rightTurnLight);
+ emit rightTurnLightChanged(rightTurnLight);
+}
+
+void CanClusterDataControl::setHeadLight(bool headLight)
+{
+ if ((m_lightStatus & HEAD_LIGHT) == headLight)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setHeadLight - status: %s", (headLight ? "on" : "off"));
+#endif
+
+ sendLightStatus(HEAD_LIGHT, headLight);
+ emit headLightChanged(headLight);
+}
+
+void CanClusterDataControl::setParkLight(bool parkLight)
+{
+ if ((m_lightStatus & PARK_LIGHT) == parkLight)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setParkLight - status: %s", (parkLight ? "on" : "off"));
+#endif
+
+ sendLightStatus(PARK_LIGHT, parkLight);
+ emit parkLightChanged(parkLight);
+}
+
+void CanClusterDataControl::setCarId(int carId)
+{
+ if (m_carId == carId)
+ return;
+
+ m_carId = carId;
+
+#ifdef _CAN_DEBUG
+ qDebug("setCarId - carId: %d", carId);
+#endif
+
+ quint16 carIdData(carId); // only 21 bits allowed (0x0 - 0x1FFFFF), pos 1.1 - 3.5 in message
+
+ QByteArray aclData;
+ aclData.append((char)(carIdData >> 13 & 0xff));
+ aclData.append((char)(carIdData >> 5 & 0xff));
+ aclData.append((char)(carIdData << 3 & 0xf8));
+ char emptyData[5] = { 0x0, 0x0, 0x0, 0x0, 0x0 };
+ aclData.append(emptyData, 5);
+ QCanBusFrame aclFrame(PGN_60928, aclData);
+ if (!m_device->writeFrame(aclFrame)) {
+ qWarning("CanClusterDataControl::setCarId - Error in pgn 60928 - Address Claimed - ACL send: %s", qPrintable(m_device->errorString()));
+ }
+
+ emit carIdChanged(carId);
+}
+
+void CanClusterDataControl::setHazardSignal(bool hazard)
+{
+ if ((m_lightStatus & HAZARD_SIGNAL) == hazard)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setHazardSignal - status: %s", (hazard ? "on" : "off"));
+#endif
+
+ sendLightStatus(HAZARD_SIGNAL, hazard);
+ emit hazardSignalChanged(hazard);
+}
+
+void CanClusterDataControl::setBrake(bool brakeOn)
+{
+ if (m_brake == brakeOn) return;
+ m_brake = brakeOn;
+
+#ifdef _CAN_DEBUG
+ qDebug("setBrake - status: %s", (brakeOn ? "on" : "off"));
+#endif
+
+ sendCCVS();
+ emit brakeChanged(brakeOn);
+}
+
+void CanClusterDataControl::setOilTemp(double oilTemp)
+{
+ if (m_oilTemp == oilTemp)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setOilTemp - level: %f", oilTemp);
+#endif
+
+ m_oilTemp = oilTemp;
+ sendET1();
+ emit oilTempChanged(oilTemp);
+}
+
+void CanClusterDataControl::setOilPressure(int oilPressure)
+{
+ if (m_oilPressure == oilPressure)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setOilPressure - level: %u", oilPressure);
+#endif
+
+ m_oilPressure = oilPressure;
+
+ QByteArray eflp1Data;
+ char emptyData[3] = { 0x0, 0x0, 0x0 };
+ eflp1Data.append(emptyData, 3);
+
+ // spn100 - Engine Oil Pressure - Gage pressure of oil in engine lubrication system as provided by oil pump.
+ // Data Length: 1 byte
+ // Resolution: 4 kPa/bit , 0 offset
+ // Data Range: 0 to 1000 kPa
+ eflp1Data.append((char)(0.25 * (double)oilPressure));
+
+ char emptyData2[4] = { 0x0, 0x0, 0x0, 0x0 };
+ eflp1Data.append(emptyData2, 4);
+ QCanBusFrame eflp1Frame(PGN_65263, eflp1Data);
+ if (!m_device->writeFrame(eflp1Frame)) {
+ qWarning("CanClusterDataControl::setOilPressure - Error in pgn 65263 - Engine Fluid Level/Pressure 1 - EFL/P1: %s", qPrintable(m_device->errorString()));
+ }
+
+ emit oilPressureChanged(oilPressure);
+}
+
+
+void CanClusterDataControl::setBatteryPotential(double batteryPotential)
+{
+ if (m_batteryPotential == batteryPotential)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setbatteryPotential - level: %f", batteryPotential);
+#endif
+
+ m_batteryPotential = batteryPotential;
+
+ // spn158 - Battery Potential (Voltage), Switched
+ // Data Length: 2 bytes
+ // Resolution: 0.05 V/bit , 0 offset
+ // Data Range: 0 to 3212.75 V
+ quint16 convertedBatteryPotential(20.0 * batteryPotential);
+
+ QByteArray vepData;
+ // 1 1 byte Net Battery Current 114
+ // 2 1 byte Alternator Current 115
+ // 3-4 2 bytes Alternator Potential (Voltage) 167
+ // 5-6 2 bytes Electrical Potential (Voltage) 168
+ char emptyData[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+ vepData.append(emptyData, 6);
+
+ vepData.append((convertedBatteryPotential >> 8 ) & 0xff);
+ vepData.append(convertedBatteryPotential & 0xff);
+
+ QCanBusFrame vepFrame(PGN_65271, vepData);
+ if (!m_device->writeFrame(vepFrame)) {
+ qWarning("CanClusterDataControl::setBatteryPotential - Error in pgn 65271 - Vehicle Electrical Power - VEP: %s", qPrintable(m_device->errorString()));
+ }
+
+ emit batteryPotentialChanged(batteryPotential);
+}
+
+void CanClusterDataControl::setGasLevel(double gasLevel)
+{
+ if (m_gasLevel == gasLevel)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setGasLevel - level: %f", gasLevel);
+#endif
+
+ m_gasLevel = gasLevel;
+
+ QByteArray ddData;
+
+ // 1 1 byte Washer Fluid Level 80
+ ddData.append((char)0x00);
+
+ // spn96 - Fuel Level - Ratio of volume of fuel to the total volume of fuel storage container.
+ // Data Length: 1 byte
+ // Resolution: 0.4 %/bit , 0 offset
+ // Data Range: 0 to 100 %
+ ddData.append((char)(2.5 * gasLevel));
+
+ // 3 1 byte Fuel Filter Differential Pressure 95
+ // 4 1 byte Engine Oil Filter Differential Pressure 99
+ // 5-6 2 bytes Cargo Ambient Temperature 169
+ // 7-8 2 bytes undefined
+ char emptyData[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+ ddData.append(emptyData, 6);
+
+ QCanBusFrame ddFrame(PGN_65276, ddData);
+ if (!m_device->writeFrame(ddFrame)) {
+ qWarning("CanClusterDataControl::setbatteryPotential - Error in pgn 65276 - Dash Display - DD: %s", qPrintable(m_device->errorString()));
+ }
+
+ emit gasLevelChanged(gasLevel);
+}
+
+void CanClusterDataControl::setRpm(int rpm)
+{
+ if (m_rpm == rpm)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setRpm - rpm: %d", rpm);
+#endif
+
+ m_rpm = rpm;
+
+ QByteArray eec1Data;
+// 1.1 4 bits Engine Torque Mode 899
+// 2 1 byte Driver's Demand Engine - Percent Torque 512
+// 3 1 byte Actual Engine - Percent Torque 513
+ char emptyData[3] = { 0x0, 0x0, 0x0 };
+ eec1Data.append(emptyData, 3);
+
+ // spn190 - Engine Speed - Actual engine speed which is calculated over a minimum crankshaft angle of 720 degrees divided by
+ // the number of cylinders.
+ // Data Length: 2 bytes
+ // Resolution: 0.125 rpm/bit , 0 offset
+ // Data Range: 0 to 8,031.875 rpm
+
+ quint16 convertedRpm(8.0 * m_rpm);
+
+ eec1Data.append((convertedRpm >> 8 ) & 0xff);
+ eec1Data.append(convertedRpm & 0xff);
+
+ // 6 1 byte Source Address of Controlling Device for Engine Control 1483
+ // 7.1 4 bits Engine Starter Mode 1675
+ // 8 1 byte Engine Demand - Percent Torque 2432
+ eec1Data.append(emptyData, 3);
+
+ QCanBusFrame eec1Frame(PGN_61444, eec1Data);
+ if (!m_device->writeFrame(eec1Frame)) {
+ qWarning("CanClusterDataControl::setbatteryPotential - Error in pgn 61444 - Electronic Engine Controller 1 - EEC1: %s", qPrintable(m_device->errorString()));
+ }
+
+ emit rpmChanged(rpm);
+}
+
+void CanClusterDataControl::setEngineTemp(int engineTemp)
+{
+ if (m_engineTemp == engineTemp)
+ return;
+
+#ifdef _CAN_DEBUG
+ qDebug("setengineTemp - engineTemp: %d", engineTemp);
+#endif
+
+ m_engineTemp = engineTemp;
+ sendET1();
+ emit engineTempChanged(engineTemp);
+}
+
+void CanClusterDataControl::sendPosition(QTime timeStamp)
+{
+#ifdef _CAN_DEBUG
+ qDebug("CanClusterDataControl::sendPosition - time stamp: %d:%d:%d.%d", timeStamp.hour(), timeStamp.minute(), timeStamp.second(), timeStamp.msec());
+#endif
+
+ QByteArray rapidPositionData;
+
+ // 10^-7 deg/bit , -210 deg offset
+ quint32 lat((m_latitude + 210.0) * 10000000.0);
+ rapidPositionData.append((lat >> 24) & 0xff);
+ rapidPositionData.append((lat >> 16) & 0xff);
+ rapidPositionData.append((lat >> 8) & 0xff);
+ rapidPositionData.append(lat & 0xff);
+
+ quint32 lon((m_longitude + 210.0) * 10000000.0);
+ rapidPositionData.append((lon >> 24) & 0xff);
+ rapidPositionData.append((lon >> 16) & 0xff);
+ rapidPositionData.append((lon >> 8) & 0xff);
+ rapidPositionData.append(lon & 0xff);
+
+ // PGN_65267 – Vehicle position - VP
+ QCanBusFrame positionFrame(PGN_65267, rapidPositionData);
+ // timestamp not needed
+ // QCanBusFrame::TimeStamp ts(timeStamp.second(), timeStamp.msec() * 1000);
+ // positionFrame.setTimeStamp(ts);
+ if (!m_device->writeFrame(positionFrame)) {
+ qWarning("CanClusterDataControl::sendPosition - Error in pgn 65267 - Vehicle position - VP: %s", qPrintable(m_device->errorString()));
+ }
+}
+
+void CanClusterDataControl::canError(QCanBusDevice::CanBusError error)
+{
+#ifdef _CAN_DEBUG
+ qDebug() << "CanClusterDataControl::canError - error:" << error << "- string:" << m_device->errorString();
+#endif
+ m_device->disconnectDevice();
+}
+
+void CanClusterDataControl::canFramesReceived()
+{
+ while (m_device->framesAvailable() > 0) {
+#ifdef _CAN_DEBUG
+ QCanBusFrame frame(m_device->readFrame());
+ QByteArray data(frame.payload());
+ qDebug() << "CanClusterDataControl::canFramesReceived - data:" << data;
+#else
+ m_device->readFrame();
+#endif
+ }
+}
+
+void CanClusterDataControl::canFramesWritten(qint64 framesCount)
+{
+#ifdef _CAN_DEBUG
+ qDebug() << "CanClusterDataControl::canFramesWritten - framesCount:" << framesCount;
+#else
+ Q_UNUSED(framesCount)
+#endif
+}
+
+void CanClusterDataControl::canStateChanged(QCanBusDevice::CanBusDeviceState state)
+{
+#ifdef _CAN_DEBUG
+ qDebug() << "CanClusterDataControl::canStateChanged - state:" << state;
+#else
+ Q_UNUSED(state)
+#endif
+}
+
+void CanClusterDataControl::sendTireConditionData(char tireId, char pressure, quint16 temperature, char status)
+{
+ QByteArray tireConditionData;
+ tireConditionData.append(tireId); // 8 bits, SPN 929 Tire Location
+ tireConditionData.append(pressure); // 8 bits, SPN 241 Tire Pressure
+
+ tireConditionData.append((char)(temperature >> 8 & 0xff));
+ tireConditionData.append((char)(temperature & 0xff));
+
+ // 5.1 2 bits CTI Wheel Sensor Status 1699, 11 = not supported
+ // 5.3 2 bits CTI Tire Status 1698, ok = 00, leak = 01
+ // 5.5 2 bits CTI Wheel End Electrical Fault 1697, 11 = not supported
+
+ tireConditionData.append(((status << 4) & 0x30) | 0xcc); // SPN 1698 CTI Tire Status
+ char emptyData[3] = { 0x0, 0x0, 0xe };
+
+ // 6-7 2 bytes Tire Air Leakage Rate 2586, 0
+ // 8.6 3 bits Tire Pressure Threshold Detection 2587, 111 = Not available
+ tireConditionData.append(emptyData, 3);
+ QCanBusFrame tireConditionFrame(PGN_65268, tireConditionData);
+ if (!m_device->writeFrame(tireConditionFrame)) {
+ qWarning("CanClusterDataControl::sendTireConditionData - Error in pgn 65268 - Tire Condition - TIRE send: %s", qPrintable(m_device->errorString()));
+ }
+}
+
+void CanClusterDataControl::sendDoorOpenStatus(quint64 door, bool open)
+{
+ if (open) {
+ m_doorStatus |= door;
+ }
+ else {
+ m_doorStatus &= ~door;
+ }
+
+ QByteArray doorOpenData;
+ doorOpenData.append((char)(m_doorStatus >> 56 & 0xff));
+ doorOpenData.append((char)(m_doorStatus >> 48 & 0xff));
+ doorOpenData.append((char)(m_doorStatus >> 40 & 0xff));
+ doorOpenData.append((char)(m_doorStatus >> 32 & 0xff));
+ doorOpenData.append((char)(m_doorStatus >> 24 & 0xff));
+ doorOpenData.append((char)(m_doorStatus >> 16 & 0xff));
+ doorOpenData.append((char)(m_doorStatus >> 8 & 0xff));
+ doorOpenData.append((char)(m_doorStatus & 0xff));
+
+ QCanBusFrame doorFrame(PGN_64933, doorOpenData); // Door Control 2 - DC2
+ if (!m_device->writeFrame(doorFrame)) {
+ qWarning("CanClusterDataControl::sendDoorOpenStatus - Error in pgn 64933 - Door Control 2 send: %s", qPrintable(m_device->errorString()));
+ }
+}
+
+void CanClusterDataControl::sendLightStatus(quint64 lightID, bool lightOn)
+{
+ if (lightOn) {
+ m_lightStatus |= lightID;
+ }
+ else {
+ m_lightStatus &= ~lightID;
+ }
+
+ QByteArray lightData;
+ lightData.append((char)(m_lightStatus >> 56 & 0xff));
+ lightData.append((char)(m_lightStatus >> 48 & 0xff));
+ lightData.append((char)(m_lightStatus >> 40 & 0xff));
+ lightData.append((char)(m_lightStatus >> 32 & 0xff));
+ lightData.append((char)(m_lightStatus >> 24 & 0xff));
+ lightData.append((char)(m_lightStatus >> 16 & 0xff));
+ lightData.append((char)(m_lightStatus >> 8 & 0xff));
+ lightData.append((char)(m_lightStatus & 0xff));
+
+ QCanBusFrame lightFrame(PGN_64972, lightData);
+ if (!m_device->writeFrame(lightFrame)) {
+ qWarning("RouteSender::sendNextData - Error in pgn 64972 - Light control send: %s", qPrintable(m_device->errorString()));
+ }
+}
+
+void CanClusterDataControl::sendCCVS()
+{
+ QByteArray ccvsData;
+ ccvsData.append((char)0x0);
+
+ // 16 bits, Wheel-Based Vehicle Speed (SPN 84), Resolution: 1/256 km/h per bit, Data Range: 0 to 250.996 km/h
+ quint16 speed(256.0 * m_vehicleSpeed);
+ ccvsData.append((speed >> 8) & 0xff);
+ ccvsData.append(speed & 0xff);
+
+ // 2 bits Brake Switch (SPN 597)
+ // 00 = pedal released
+ // 01 = pedal depressed
+ if (m_brake) {
+ ccvsData.append((char)0x10);
+ }
+ else {
+ ccvsData.append((char)0x00);
+ }
+ char emptyData[4] = { 0x0, 0x0, 0x0, 0x0 };
+ ccvsData.append(emptyData, 4);
+ QCanBusFrame ccvsFrame(PGN_65265, ccvsData);
+ if (!m_device->writeFrame(ccvsFrame)) {
+ qWarning("CanClusterDataControl::sendCCVS - Error in pgn 65265 - Cruise Control/Vehicle Speed - CCVS: %s", qPrintable(m_device->errorString()));
+ }
+}
+
+void CanClusterDataControl::sendET1()
+{
+ QByteArray et1Data;
+ // SPN 110 - Engine Coolant Temperature
+ // Data Length: 1 byte
+ // Resolution: 1 deg C/bit , -40 deg C offset
+ // Data Range: -40 to 210 deg C
+ et1Data.append((quint8)(m_engineTemp + 40));
+ et1Data.append((char)0x00); // SPN 174 Fuel Temperature
+ // spn175 - Engine Oil Temperature 1 - Temperature of the engine lubricant.
+ // Data Length: 2 bytes
+ // Resolution: 0.03125 deg C/bit , -273 deg C offset
+ // Data Range: -273 to 1735 deg C
+ quint16 convertedEngOilTemp(32.0 * (m_oilTemp + 273.0));
+ et1Data.append((convertedEngOilTemp >> 8) & 0xff);
+ et1Data.append(convertedEngOilTemp & 0xff);
+ // 5-6 2 bytes Turbo Oil Temperature 176
+ // 7 1 byte Engine Intercooler Temperature 52
+ // 8 1 byte Engine Intercooler Thermostat Opening 1134
+ char emptyData[4] = { 0x0, 0x0, 0x0, 0x0 };
+ et1Data.append(emptyData, 4);
+ QCanBusFrame et1Frame(PGN_65262, et1Data);
+ if (!m_device->writeFrame(et1Frame)) {
+ qWarning("CanClusterDataControl::sendET1 - Error in pgn 65262 - Engine Temperature 1 - ET1: %s", qPrintable(m_device->errorString()));
+ }
+}
diff --git a/CanController/canclusterdatacontrol.h b/CanController/canclusterdatacontrol.h
new file mode 100644
index 0000000..1708c8a
--- /dev/null
+++ b/CanController/canclusterdatacontrol.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CANCLUSTERDATACONTROL_H
+#define CANCLUSTERDATACONTROL_H
+
+#include "clusterdatacontrolinterface.h"
+#include <QTime>
+#include <QCanBusDevice>
+
+class CanClusterDataControl : public ClusterDataControlInterface
+{
+ Q_OBJECT
+
+public:
+ CanClusterDataControl(QObject* parent = Q_NULLPTR);
+
+public: // from class ClusterDataControlInterface
+ virtual int carId() const;
+ virtual bool headLight() const;
+ virtual bool parkLight() const;
+ virtual bool rightTurnLight() const;
+ virtual bool leftTurnLight() const;
+ virtual int gear() const;
+ virtual bool lightFailure() const;
+ virtual bool frontLeftDoorOpen() const;
+ virtual bool frontRightDoorOpen() const;
+ virtual bool rearLeftDoorOpen() const;
+ virtual bool rearRightDoorOpen() const;
+ virtual bool hoodOpen() const;
+ virtual bool trunkOpen() const;
+ virtual bool flatTire() const;
+ virtual double direction() const;
+ virtual double longitude() const;
+ virtual double latitude() const;
+ virtual double vehicleSpeed() const;
+ virtual bool hazardSignal() const;
+ virtual bool brake() const;
+ virtual double oilTemp() const;
+ virtual int oilPressure() const;
+ virtual double batteryPotential() const;
+ virtual double gasLevel() const;
+ virtual int rpm() const;
+ virtual int engineTemp() const;
+
+public slots: // from class ClusterDataControlInterface
+ virtual void setVehicleSpeed(double vehicleSpeed);
+ virtual void setLatitude(double latitude);
+ virtual void setLongitude(double longitude);
+ virtual void setDirection(double direction);
+ virtual void setFlatTire(bool flatTire);
+ virtual void setFrontLeftDoorOpen(bool doorOpen);
+ virtual void setFrontRightDoorOpen(bool doorOpen);
+ virtual void setRearLeftDoorOpen(bool doorOpen);
+ virtual void setRearRightDoorOpen(bool doorOpen);
+ virtual void setHoodOpen(bool doorOpen);
+ virtual void setTrunkOpen(bool doorOpen);
+ virtual void setLightFailure(bool lightFailure);
+ virtual void setGear(int gear);
+ virtual void setLeftTurnLight(bool leftTurnLight);
+ virtual void setRightTurnLight(bool rightTurnLight);
+ virtual void setHeadLight(bool headLight);
+ virtual void setParkLight(bool parkLight);
+ virtual void setCarId(int carId);
+ virtual void setHazardSignal(bool hazard);
+ virtual void setBrake(bool brakeOn);
+ virtual void setOilTemp(double oilTemp);
+ virtual void setOilPressure(int oilPressure);
+ virtual void setBatteryPotential (double batteryPotential);
+ virtual void setGasLevel(double gasLevel);
+ virtual void setRpm(int rpm);
+ virtual void setEngineTemp(int engineTemp);
+
+public slots: // new local slots
+ void sendPosition(QTime timeStamp);
+
+private slots:
+ void canError(QCanBusDevice::CanBusError error);
+ void canFramesReceived();
+ void canFramesWritten(qint64 framesCount);
+ void canStateChanged(QCanBusDevice::CanBusDeviceState state);
+
+private:
+ void sendTireConditionData(char tireId, char pressure, quint16 temperature, char status);
+ void sendDoorOpenStatus(quint64 door, bool open);
+ void sendLightStatus(quint64 lightID, bool lightOn);
+ void sendCCVS();
+ void sendET1();
+
+private: // data
+ class QCanBus* m_canBus;
+ class QCanBusDevice* m_device;
+ quint64 m_doorStatus;
+ quint64 m_lightStatus;
+ bool m_brake;
+};
+
+#endif // CANCLUSTERDATACONTROL_H
diff --git a/CanController/carui.qrc b/CanController/carui.qrc
new file mode 100644
index 0000000..8eb3ccb
--- /dev/null
+++ b/CanController/carui.qrc
@@ -0,0 +1,70 @@
+<RCC>
+ <qresource prefix="/">
+ <file>Button.qml</file>
+ <file>ButtonHolder.qml</file>
+ <file>Car.qml</file>
+ <file>CarUI.qml</file>
+ <file>Gear.qml</file>
+ <file>GearAutomatic.qml</file>
+ <file>Icon_BulbFailure_OFF.png</file>
+ <file>Icon_BulbFailure_ON.png</file>
+ <file>Icon_HazardWarning_OFF.png</file>
+ <file>Icon_HazardWarning_ON.png</file>
+ <file>Icon_LowBeam_OFF.png</file>
+ <file>Icon_LowBeam_ON.png</file>
+ <file>Icon_TurnLeft_OFF.png</file>
+ <file>Icon_TurnLeft_ON.png</file>
+ <file>Icon_TurnRight_OFF.png</file>
+ <file>Icon_TurnRight_ON.png</file>
+ <file>Icon_TyreMalfunction_OFF.png</file>
+ <file>Icon_TyreMalfunction_ON.png</file>
+ <file>Slide.qml</file>
+ <file>SlideHolder.qml</file>
+ <file>S-Car_BrakesOFF.png</file>
+ <file>S-Car_BrakesON.png</file>
+ <file>S-Car_DoorLeftOFF.png</file>
+ <file>S-Car_DoorLeftON.png</file>
+ <file>S-Car_DoorRightOFF.png</file>
+ <file>S-Car_DoorRightON.png</file>
+ <file>S-Car_HoodOFF.png</file>
+ <file>S-Car_HoodON.png</file>
+ <file>S-Car_LowBeamsOFF.png</file>
+ <file>S-Car_LowBeamsON.png</file>
+ <file>S-Car_Shape.png</file>
+ <file>S-Car_TrunkOFF.png</file>
+ <file>S-Car_TrunkON.png</file>
+ <file>S-Car_TurnLeftOFF.png</file>
+ <file>S-Car_TurnLeftON.png</file>
+ <file>S-Car_TurnRightOFF.png</file>
+ <file>S-Car_TurnRightON.png</file>
+ <file>E-Car_BackDoorLeftOFF.png</file>
+ <file>E-Car_BackDoorLeftON.png</file>
+ <file>E-Car_BackDoorRightOFF.png</file>
+ <file>E-Car_BackDoorRightON.png</file>
+ <file>E-Car_BrakesOFF.png</file>
+ <file>E-Car_BrakesON.png</file>
+ <file>E-Car_FrontDoorLeftOFF.png</file>
+ <file>E-Car_FrontDoorLeftON.png</file>
+ <file>E-Car_FrontDoorRightOFF.png</file>
+ <file>E-Car_FrontDoorRightON.png</file>
+ <file>E-Car_HoodOFF.png</file>
+ <file>E-Car_HoodON.png</file>
+ <file>E-Car_LowBeamsOFF.png</file>
+ <file>E-Car_LowBeamsON.png</file>
+ <file>E-Car_Shape.png</file>
+ <file>E-Car_TrunkOFF.png</file>
+ <file>E-Car_TrunkON.png</file>
+ <file>E-Car_TurnLeftOFF.png</file>
+ <file>E-Car_TurnLeftON.png</file>
+ <file>E-Car_TurnRightOFF.png</file>
+ <file>E-Car_TurnRightON.png</file>
+ <file>ViewChange.qml</file>
+ <file>CenterViewOff.png</file>
+ <file>CenterViewOn.png</file>
+ <file>route.txt</file>
+ <file>Icon_ParkingBrake_OFF.png</file>
+ <file>Icon_ParkingBrake_ON.png</file>
+ <file>CenterViewOffOpt.png</file>
+ <file>CenterViewOnOpt.png</file>
+ </qresource>
+</RCC>
diff --git a/CanController/clusterdatacontrolinterface.h b/CanController/clusterdatacontrolinterface.h
new file mode 100644
index 0000000..1e11dc1
--- /dev/null
+++ b/CanController/clusterdatacontrolinterface.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLUSTERDATACONTROLINTERFACE_H
+#define CLUSTERDATACONTROLINTERFACE_H
+
+#include <QObject>
+
+class ClusterDataControlInterface : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(double vehicleSpeed READ vehicleSpeed WRITE setVehicleSpeed NOTIFY vehicleSpeedChanged)
+ Q_PROPERTY(double latitude READ latitude WRITE setLatitude NOTIFY latitudeChanged)
+ Q_PROPERTY(double longitude READ longitude WRITE setLongitude NOTIFY longitudeChanged)
+ Q_PROPERTY(double direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(bool flatTire READ flatTire WRITE setFlatTire NOTIFY flatTireChanged)
+ Q_PROPERTY(bool frontLeftDoorOpen READ frontLeftDoorOpen WRITE setFrontLeftDoorOpen NOTIFY frontLeftDoorOpenChanged)
+ Q_PROPERTY(bool frontRightDoorOpen READ frontRightDoorOpen WRITE setFrontRightDoorOpen NOTIFY frontRightDoorOpenChanged)
+ Q_PROPERTY(bool rearLeftDoorOpen READ rearLeftDoorOpen WRITE setRearLeftDoorOpen NOTIFY rearLeftDoorOpenChanged)
+ Q_PROPERTY(bool rearRightDoorOpen READ rearRightDoorOpen WRITE setRearRightDoorOpen NOTIFY rearRightDoorOpenChanged)
+ Q_PROPERTY(bool lightFailure READ lightFailure WRITE setLightFailure NOTIFY lightFailureChanged)
+ Q_PROPERTY(bool trunkOpen READ trunkOpen WRITE setTrunkOpen NOTIFY trunkOpenChanged)
+ Q_PROPERTY(bool hoodOpen READ hoodOpen WRITE setHoodOpen NOTIFY hoodOpenChanged)
+ Q_PROPERTY(int gear READ gear WRITE setGear NOTIFY gearChanged)
+ Q_PROPERTY(bool leftTurnLight READ leftTurnLight WRITE setLeftTurnLight NOTIFY leftTurnLightChanged)
+ Q_PROPERTY(bool rightTurnLight READ rightTurnLight WRITE setRightTurnLight NOTIFY rightTurnLightChanged)
+ Q_PROPERTY(bool headLight READ headLight WRITE setHeadLight NOTIFY headLightChanged)
+ Q_PROPERTY(bool parkLight READ parkLight WRITE setParkLight NOTIFY parkLightChanged)
+ Q_PROPERTY(int carId READ carId WRITE setCarId NOTIFY carIdChanged)
+ Q_PROPERTY(bool hazardSignal READ hazardSignal WRITE setHazardSignal NOTIFY hazardSignalChanged)
+ Q_PROPERTY(bool brake READ brake WRITE setBrake NOTIFY brakeChanged)
+ Q_PROPERTY(double oilTemp READ oilTemp WRITE setOilTemp NOTIFY oilTempChanged)
+ Q_PROPERTY(int oilPressure READ oilPressure WRITE setOilPressure NOTIFY oilPressureChanged)
+ Q_PROPERTY(double batteryPotential READ batteryPotential WRITE setBatteryPotential NOTIFY batteryPotentialChanged)
+ Q_PROPERTY(double gasLevel READ gasLevel WRITE setGasLevel NOTIFY gasLevelChanged)
+ Q_PROPERTY(int rpm READ rpm WRITE setRpm NOTIFY rpmChanged)
+ Q_PROPERTY(int engineTemp READ engineTemp WRITE setEngineTemp NOTIFY engineTempChanged)
+public:
+ ClusterDataControlInterface(QObject *parent) :
+ QObject(parent),
+ m_carId(2),
+ m_gear(1),
+ m_lightFailure(false),
+ m_flatTire(false),
+ m_direction(0.0),
+ m_longitude(0.0),
+ m_latitude(0.0),
+ m_vehicleSpeed(0.0),
+ m_oilTemp(40.0),
+ m_oilPressure(0),
+ m_batteryPotential(80.0),
+ m_gasLevel(67.0),
+ m_rpm(4000),
+ m_engineTemp(60)
+ {}
+
+ virtual int carId() const = 0;
+ virtual bool headLight() const = 0;
+ virtual bool parkLight() const = 0;
+ virtual bool rightTurnLight() const = 0;
+ virtual bool leftTurnLight() const = 0;
+ virtual int gear() const = 0;
+ virtual bool lightFailure() const = 0;
+ virtual bool frontLeftDoorOpen() const = 0;
+ virtual bool frontRightDoorOpen() const = 0;
+ virtual bool rearLeftDoorOpen() const = 0;
+ virtual bool rearRightDoorOpen() const = 0;
+ virtual bool hoodOpen() const = 0;
+ virtual bool trunkOpen() const = 0;
+ virtual bool flatTire() const = 0;
+ virtual double direction() const = 0;
+ virtual double longitude() const = 0;
+ virtual double latitude() const = 0;
+ virtual double vehicleSpeed() const = 0;
+ virtual bool hazardSignal() const = 0;
+ virtual bool brake() const = 0;
+ virtual double oilTemp() const = 0;
+ virtual int oilPressure() const = 0;
+ virtual double batteryPotential() const = 0;
+ virtual double gasLevel() const = 0;
+ virtual int rpm() const = 0;
+ virtual int engineTemp() const = 0;
+
+public slots:
+ virtual void setVehicleSpeed(double vehicleSpeed) = 0;
+ virtual void setLatitude(double latitude) = 0;
+ virtual void setLongitude(double longitude) = 0;
+ virtual void setDirection(double direction) = 0;
+ virtual void setFlatTire(bool flatTire) = 0;
+ virtual void setFrontLeftDoorOpen(bool doorOpen) = 0;
+ virtual void setFrontRightDoorOpen(bool doorOpen) = 0;
+ virtual void setRearLeftDoorOpen(bool doorOpen) = 0;
+ virtual void setRearRightDoorOpen(bool doorOpen) = 0;
+ virtual void setHoodOpen(bool doorOpen) = 0;
+ virtual void setTrunkOpen(bool doorOpen) = 0;
+ virtual void setLightFailure(bool lightFailure) = 0;
+ virtual void setGear(int gear) = 0;
+ virtual void setLeftTurnLight(bool leftTurnLight) = 0;
+ virtual void setRightTurnLight(bool rightTurnLight) = 0;
+ virtual void setHeadLight(bool headLight) = 0;
+ virtual void setParkLight(bool parkLight) = 0;
+ virtual void setCarId(int carId) = 0;
+ virtual void setHazardSignal(bool) = 0;
+ virtual void setBrake(bool) = 0;
+ virtual void setOilTemp(double oilTemp) = 0;
+ virtual void setOilPressure(int oilPressure) = 0;
+ virtual void setBatteryPotential(double batteryPotential) = 0;
+ virtual void setGasLevel(double gasLevel) = 0;
+ virtual void setRpm(int rpm) = 0;
+ virtual void setEngineTemp(int engineTemp) = 0;
+
+signals:
+ void dataReset();
+ void carIdChanged(int carId);
+ void headLightChanged(bool headLight);
+ void parkLightChanged(bool parkLight);
+ void rightTurnLightChanged(bool rightTurnLight);
+ void leftTurnLightChanged(bool leftTurnLight);
+ void gearChanged(bool gear);
+ void lightFailureChanged(bool lightFailure);
+ void frontLeftDoorOpenChanged(bool doorOpen);
+ void frontRightDoorOpenChanged(bool doorOpen);
+ void rearLeftDoorOpenChanged(bool doorOpen);
+ void rearRightDoorOpenChanged(bool doorOpen);
+ void hoodOpenChanged(bool doorOpen);
+ void trunkOpenChanged(bool doorOpen);
+ void flatTireChanged(bool flatTire);
+ void directionChanged(double direction);
+ void longitudeChanged(double longitude);
+ void latitudeChanged(double latitude);
+ void vehicleSpeedChanged(double vehicleSpeed);
+ void hazardSignalChanged(bool hazard);
+ void brakeChanged(bool brakeOn);
+ void oilTempChanged(double oilTemp);
+ void oilPressureChanged(int oilPressure);
+ void batteryPotentialChanged(double batteryPotential);
+ void gasLevelChanged(double gasLevel);
+ void rpmChanged(int rpm);
+ void engineTempChanged(int engineTemp);
+
+protected:
+ int m_carId;
+ int m_gear;
+ bool m_lightFailure;
+ bool m_flatTire;
+ double m_direction;
+ double m_longitude;
+ double m_latitude;
+ double m_vehicleSpeed;
+ double m_oilTemp;
+ int m_oilPressure;
+ double m_batteryPotential;
+ double m_gasLevel;
+ int m_rpm;
+ int m_engineTemp;
+
+};
+
+#endif // CLUSTERDATACONTROLINTERFACE_H
diff --git a/CanController/gpssender.cpp b/CanController/gpssender.cpp
new file mode 100644
index 0000000..a5ffb32
--- /dev/null
+++ b/CanController/gpssender.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gpssender.h"
+#include "nmea.h"
+
+#include <QFile>
+#include <QDebug>
+
+GpsSender::GpsSender(QString routeFileName, QObject* parent) :
+ QObject(parent),
+ m_dataPosition(0),
+ m_nmea(Q_NULLPTR),
+ m_latitude(0.0),
+ m_longitude(0.0),
+ m_direction(0.0),
+ m_vehicleSpeed(0.0)
+{
+ parseRouteFile(routeFileName);
+ m_timer.setSingleShot(true);
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(nextData()), Qt::QueuedConnection);
+ m_nmea = NMEA::parse(m_data.at(m_dataPosition));
+ QMetaObject::invokeMethod(this, "nextData", Qt::QueuedConnection);
+}
+
+GpsSender::~GpsSender()
+{
+ delete m_nmea;
+}
+
+void GpsSender::parseRouteFile(QString routeFileName)
+{
+ QFile routeFile(routeFileName);
+ if (!routeFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("GpsSender::parseRouteFile - Error opening route file: %s", qPrintable(routeFileName));
+ return;
+ }
+ while (!routeFile.atEnd()) {
+ m_data.append(routeFile.readLine().simplified());
+ }
+ routeFile.close();
+}
+
+void GpsSender::nextData()
+{
+ if (m_nmea) {
+ NMEAType::Type type(m_nmea->type());
+ bool convertOk(false);
+
+ if (type != NMEAType::UndefinedType) {
+ qreal position(m_nmea->value(NMEAType::Latitude).toDouble(&convertOk));
+#ifndef TCPCLUSTERDATACONNECTION
+ bool posChanged(false);
+#endif
+ if (convertOk && m_latitude != position) {
+ m_latitude = position;
+ emit latitudeChanged(m_latitude);
+#ifndef TCPCLUSTERDATACONNECTION
+ posChanged = true;
+#endif
+ }
+ position = m_nmea->value(NMEAType::Longitude).toDouble(&convertOk);
+ if (convertOk && m_longitude != position) {
+ m_longitude = position;
+ emit longitudeChanged(m_longitude);
+#ifndef TCPCLUSTERDATACONNECTION
+ posChanged = true;
+#endif
+ }
+#ifndef TCPCLUSTERDATACONNECTION
+// qDebug("GpsSender::nextData - posChanged: %s, m_timeStamp is valid: %s", (posChanged ? "true" : "false"), (m_timeStamp.isValid() ? "true" : "false"));
+ if (posChanged && m_timeStamp.isValid()) {
+ emit positionChanged(m_timeStamp);
+ }
+#endif
+ }
+
+ if (type == NMEAType::RMCType) {
+ qreal convertedValue(m_nmea->value(NMEAType::RMCAngle).toDouble(&convertOk));
+ if (convertOk && m_direction != convertedValue) {
+ m_direction = convertedValue;
+ emit directionChanged(m_direction);
+ }
+ convertedValue = m_nmea->value(NMEAType::RMCSpeed).toDouble(&convertOk);
+ if (convertOk && m_vehicleSpeed != convertedValue) {
+ m_vehicleSpeed = convertedValue;
+ emit vehicleSpeedChanged(m_vehicleSpeed);
+ }
+ }
+ }
+
+ delete m_nmea;
+ if (++m_dataPosition >= m_data.count()) {
+ m_dataPosition = 0;
+ }
+
+ m_nmea = NMEA::parse(m_data.at(m_dataPosition));
+
+ if (m_nmea) {
+ QTime timeStamp(m_nmea->value(NMEAType::UTCTime).toTime());
+ int mseconds(m_timeStamp.msecsTo(timeStamp));
+ m_timeStamp = timeStamp;
+ if (mseconds > 0) {
+ m_timer.start(mseconds);
+ }
+ else {
+ QMetaObject::invokeMethod(this, "nextData", Qt::QueuedConnection);
+ }
+ }
+ else {
+ m_timeStamp = QTime();
+ qWarning("GpsSender::nextData - Error in NMEA parsing");
+ }
+}
diff --git a/CanController/gpssender.h b/CanController/gpssender.h
new file mode 100644
index 0000000..0fc595e
--- /dev/null
+++ b/CanController/gpssender.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GPSSENDER_H
+#define GPSSENDER_H
+
+#include <QObject>
+#include <QTimer>
+#include <QTime>
+
+class GpsSender : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit GpsSender(QString routeFileName, QObject* parent = Q_NULLPTR);
+ virtual ~GpsSender();
+
+private:
+ void parseRouteFile(QString routeFileName);
+
+signals:
+ void latitudeChanged(qreal latitude);
+ void longitudeChanged(qreal longitude);
+ void directionChanged(qreal direction);
+ void vehicleSpeedChanged(qreal vehicleSpeed);
+#ifndef TCPCLUSTERDATACONNECTION
+ void positionChanged(QTime timeStamp);
+#endif
+
+private slots:
+ void nextData();
+
+private: // data
+ QStringList m_data;
+ QTimer m_timer;
+ int m_dataPosition;
+ class NMEA* m_nmea;
+ qreal m_latitude;
+ qreal m_longitude;
+ qreal m_direction;
+ qreal m_vehicleSpeed;
+ QTime m_timeStamp;
+
+};
+
+#endif // GPSSENDER_H
diff --git a/CanController/main.cpp b/CanController/main.cpp
new file mode 100644
index 0000000..b50e5cc
--- /dev/null
+++ b/CanController/main.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQuickView>
+#include <QObject>
+#include <QQmlEngine>
+#include <QQmlContext>
+
+#include "gpssender.h"
+
+#ifdef TCPCLUSTERDATACONNECTION
+#include "tcpclusterdatacontrol.h"
+#else
+#include <QTime>
+#include "canclusterdatacontrol.h"
+#endif
+
+int main(int argc, char** argv)
+{
+ QGuiApplication app(argc, argv);
+
+ ClusterDataControlInterface* dataInterface(Q_NULLPTR);
+
+#ifdef TCPCLUSTERDATACONNECTION
+ dataInterface = new TCPClusterDataControl;
+#else
+ dataInterface = new CanClusterDataControl;
+#endif
+
+ Q_ASSERT(dataInterface);
+
+ QString routeFileName(DEFAULT_ROUTE_FILE);
+ QStringList args(app.arguments());
+ if (args.count() > 1) {
+ routeFileName = args.at(1);
+ }
+
+ GpsSender gpsSender(routeFileName);
+
+ QObject::connect(&gpsSender, SIGNAL(latitudeChanged(qreal)), dataInterface, SLOT(setLatitude(double)));
+ QObject::connect(&gpsSender, SIGNAL(longitudeChanged(qreal)), dataInterface, SLOT(setLongitude(double)));
+ QObject::connect(&gpsSender, SIGNAL(directionChanged(qreal)), dataInterface, SLOT(setDirection(double)));
+ QObject::connect(&gpsSender, SIGNAL(vehicleSpeedChanged(qreal)), dataInterface, SLOT(setVehicleSpeed(double)));
+
+#ifndef TCPCLUSTERDATACONNECTION
+ QObject::connect(&gpsSender, SIGNAL(positionChanged(QTime)), qobject_cast<CanClusterDataControl*>(dataInterface), SLOT(sendPosition(QTime)));
+#endif
+
+ QQuickView view;
+
+ view.rootContext()->setContextProperty("clusterDataControl", dataInterface);
+
+ QObject::connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));
+
+ view.setSource(QUrl(MAIN_QML_FILE_NAME));
+
+ view.show();
+
+ return app.exec();
+}
diff --git a/CanController/nmea.cpp b/CanController/nmea.cpp
new file mode 100644
index 0000000..a73361d
--- /dev/null
+++ b/CanController/nmea.cpp
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "nmea.h"
+
+#include <QObject>
+#include <QtMath>
+
+#include <QDebug>
+
+
+// NMEAPrivate
+struct NMEAPrivate
+{
+ NMEAPrivate() : m_checksum(0), m_type(NMEAType::UndefinedType) {
+ }
+ int m_checksum;
+ NMEAType::Type m_type;
+ QTime m_taken;
+};
+
+
+// NMEA
+NMEA::NMEA() : m_private(new NMEAPrivate)
+{
+}
+
+NMEA::~NMEA()
+{
+ delete m_private;
+ m_private = NULL;
+}
+
+NMEA* NMEA::parse(QString data)
+{
+ NMEA* nmea(Q_NULLPTR);
+
+ int lastIndex(data.lastIndexOf("*"));
+ int checksum(0);
+ for (int index(data.indexOf("$") + 1); index < lastIndex; index++) {
+ checksum ^= (int)data.at(index).toLatin1();
+ }
+
+ QString checksumString(QString::number(checksum, 16));
+ if (checksum <= 0xf) {
+ checksumString.prepend("0");
+ }
+ QString compareChecksum(data.mid(lastIndex + 1));
+ if (compareChecksum.compare(checksumString)) {
+ qWarning("NMEA::parse - Error invalid checksum %s != %s", qPrintable(compareChecksum), qPrintable(QString::number(checksum, 16)));
+ return nmea;
+ }
+
+ QStringList dataList(data.left(lastIndex).split(","));
+ if (dataList.count() <= 1) {
+ return nmea;
+ }
+
+ QString type(dataList.at(0));
+
+ if (type.compare("$GPGGA", Qt::CaseInsensitive) == 0) {
+ nmea = new GGA(dataList);
+ }
+
+ else if (type.compare("$GPRMC", Qt::CaseInsensitive) == 0) {
+ nmea = new RMC(dataList);
+ }
+
+ if (!nmea) {
+ qWarning("NMEA::parse - Error NMEA creation error");
+ }
+ else if (nmea->isValid()) {
+ nmea->m_private->m_checksum = checksum;
+ }
+ else {
+ qWarning("NMEA::parse - Error NMEA is not valid, deleting it");
+ delete nmea;
+ nmea = Q_NULLPTR;
+ }
+
+ return nmea;
+}
+
+bool NMEA::isValid() const
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ return (m_private && m_private->m_type != NMEAType::UndefinedType);
+}
+
+NMEAType::Type NMEA::type() const
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ return (m_private ? m_private->m_type : NMEAType::UndefinedType);
+}
+
+QVariant NMEA::value(NMEAType::Value type) const
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type == NMEAType::UTCTime) {
+ return QVariant::fromValue<QTime>(m_private->m_taken);
+ }
+ else if (type == NMEAType::CheckSum) {
+ return QVariant::fromValue<int>(m_private->m_checksum);
+ }
+ else return QVariant();
+}
+
+void NMEA::setValue(NMEAType::Value type, QVariant value)
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type == NMEAType::UTCTime && value.type() == QVariant::Time) {
+ m_private->m_taken = value.toTime();
+ }
+ else if (type == NMEAType::CheckSum && value.type() == QVariant::Int) {
+ m_private->m_checksum = value.toInt();
+ }
+}
+
+// GeoBasePrivate
+struct GeoBasePrivate : public NMEAPrivate
+{
+ GeoBasePrivate() : m_latitude(0.0), m_longitude(0.0) {
+ }
+ qreal m_latitude;
+ qreal m_longitude;
+};
+
+
+// GeoBasePrivate
+GeoBase::GeoBase()
+{
+}
+
+GeoBase::~GeoBase()
+{
+}
+
+QVariant GeoBase::value(NMEAType::Value type) const
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type >= (NMEAType::Value)NMEAType::NMEAStart && type <= (NMEAType::Value)NMEAType::NMEAEnd) {
+ return NMEA::value(type);
+ }
+ else {
+ GeoBasePrivate* geoBasePrivate((GeoBasePrivate*)m_private);
+ switch (type) {
+ case NMEAType::Latitude : return QVariant::fromValue<qreal>(geoBasePrivate->m_latitude);
+ case NMEAType::Longitude : return QVariant::fromValue<qreal>(geoBasePrivate->m_longitude);
+ default: /* do nothing */ break;
+ }
+ }
+ return QVariant();
+}
+
+void GeoBase::setValue(NMEAType::Value type, QVariant value)
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type >= (NMEAType::Value)NMEAType::NMEAStart && type <= (NMEAType::Value)NMEAType::NMEAEnd) {
+ NMEA::setValue(type, value);
+ }
+ else {
+ GeoBasePrivate* geoBasePrivate((GeoBasePrivate*)m_private);
+ switch (type) {
+ case NMEAType::Latitude : geoBasePrivate->m_latitude = value.toDouble(); break;
+ case NMEAType::Longitude : geoBasePrivate->m_longitude = value.toDouble(); break;
+ default: /* do nothing */ break;
+ }
+ }
+}
+
+
+// GGA
+struct GGAPrivate : public GeoBasePrivate
+{
+ GGAPrivate() : m_quality(0), m_satellites(0), m_dilution(0.0), m_altitude(0.0), m_geoid(0.0) {
+ }
+ int m_quality;
+ int m_satellites;
+ qreal m_dilution;
+ qreal m_altitude;
+ qreal m_geoid;
+};
+
+GGA::~GGA() {
+}
+
+QVariant GGA::value(NMEAType::Value type) const
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type >= (NMEAType::Value)NMEAType::NMEAStart && type <= (NMEAType::Value)NMEAType::GeoBaseEnd) {
+ return GeoBase::value(type);
+ }
+ else {
+ GGAPrivate* ggaPrivate((GGAPrivate*)m_private);
+ switch (type) {
+ case NMEAType::GGAQuality : return QVariant::fromValue<int>(ggaPrivate->m_quality);
+ case NMEAType::GGASatellites : return QVariant::fromValue<int>(ggaPrivate->m_satellites);
+ case NMEAType::GGADilution : return QVariant::fromValue<qreal>(ggaPrivate->m_dilution);
+ case NMEAType::GGAAltitude : return QVariant::fromValue<qreal>(ggaPrivate->m_altitude);
+ case NMEAType::GGAGeoid : return QVariant::fromValue<qreal>(ggaPrivate->m_geoid);
+ default: /* do nothing */ break;
+ }
+ }
+ return QVariant();
+
+}
+
+void GGA::setValue(NMEAType::Value type, QVariant value)
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type >= (NMEAType::Value)NMEAType::NMEAStart && type <= (NMEAType::Value)NMEAType::GeoBaseEnd) {
+ return GeoBase::setValue(type, value);
+ }
+ else {
+ GGAPrivate* ggaPrivate((GGAPrivate*)m_private);
+ switch (type) {
+ case NMEAType::GGAQuality : ggaPrivate->m_quality = value.toInt(); break;
+ case NMEAType::GGASatellites : ggaPrivate->m_satellites = value.toInt(); break;
+ case NMEAType::GGADilution : ggaPrivate->m_dilution = value.toDouble(); break;
+ case NMEAType::GGAAltitude : ggaPrivate->m_altitude = value.toDouble(); break;
+ case NMEAType::GGAGeoid : ggaPrivate->m_geoid = value.toDouble(); break;
+ default: /* do nothing */ break;
+ }
+ }
+}
+
+GGA::GGA(QStringList data)
+{
+ GGAPrivate* newPrivate = new GGAPrivate;
+ if (data.count() == 15) {
+ QString utcTime(data.at(1));
+ if (utcTime.length() > 6) {
+ newPrivate->m_taken = QTime::fromString(utcTime, "hhmmss.z");
+ }
+ else {
+ newPrivate->m_taken = QTime::fromString(utcTime, "hhmmss");
+ }
+
+ bool ok(false);
+ qreal position(data.at(2).toDouble(&ok));
+ if (ok) {
+ qreal degrees(qFloor(0.01 * position));
+ newPrivate->m_latitude = (degrees + ((position - (100.0 * degrees)) / 60));
+ if (data.at(3).compare("S", Qt::CaseInsensitive) == 0) {
+ newPrivate->m_latitude *= -1.0;
+ }
+ }
+ else {
+ qWarning("GGA::GGA - Error in latitude parse");
+ }
+
+ position = data.at(4).toDouble(&ok);
+ if (ok) {
+ qreal degrees(qFloor(0.01 * position));
+ newPrivate->m_longitude = (degrees + ((position - (100.0 * degrees)) / 60));
+ if (data.at(5).compare("W", Qt::CaseInsensitive) == 0) {
+ newPrivate->m_longitude *= -1.0;
+ }
+ }
+ else {
+ qWarning("GGA::GGA - Error in longitude parse");
+ }
+ newPrivate->m_quality = data.at(6).toInt(&ok);
+ if (!ok) {
+ qWarning("GGA::GGA - Error in quality parse");
+ }
+ newPrivate->m_satellites = data.at(7).toInt(&ok);
+ if (!ok) {
+ qWarning("GGA::GGA - Error in satellites parse");
+ }
+ newPrivate->m_dilution = data.at(8).toDouble(&ok);
+ if (!ok) {
+ qWarning("GGA::GGA - Error in dilution parse");
+ }
+ newPrivate->m_altitude = data.at(9).toDouble(&ok);
+ if (!ok) {
+ qWarning("GGA::GGA - Error in altitude parse");
+ }
+ if (data.at(10).compare("M")) {
+ qWarning("GGA::GGA - Error in altitude type parse");
+ }
+ newPrivate->m_geoid = data.at(11).toDouble(&ok);
+ if (!ok) {
+ qWarning("GGA::GGA - Error in height of geoid parse");
+ }
+ if (data.at(12).compare("M")) {
+ qWarning("GGA::GGA - Error in height of geoid type parse");
+ }
+ if (!data.at(13).isEmpty()) {
+ qWarning("GGA::GGA - Error in not empty field 14 - data: %s", qPrintable(data.at(13)));
+ }
+ if (!data.at(14).isEmpty()) {
+ qWarning("GGA::GGA - Error in not empty field 15 - data: %s", qPrintable(data.at(14)));
+ }
+ }
+ else {
+ qWarning("GGA::GGA - Error incorrect amount of data %d available!", data.count());
+ }
+ delete m_private;
+ newPrivate->m_type = NMEAType::GGAType;
+ m_private = newPrivate;
+}
+
+
+// RMC
+struct RMCPrivate : public GeoBasePrivate
+{
+ RMCPrivate() : m_active(false), m_speed(0.0), m_angle(0.0), m_variation(0.0) {
+ }
+ bool m_active;
+ qreal m_speed;
+ qreal m_angle;
+ QDate m_date;
+ qreal m_variation;
+};
+
+RMC::~RMC()
+{
+}
+
+QVariant RMC::value(NMEAType::Value type) const
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type >= (NMEAType::Value)NMEAType::NMEAStart && type <= (NMEAType::Value)NMEAType::GeoBaseEnd) {
+ return GeoBase::value(type);
+ }
+ else {
+ RMCPrivate* rmcPrivate((RMCPrivate*)m_private);
+ switch (type) {
+ case NMEAType::RMCActive : return QVariant::fromValue<bool>(rmcPrivate->m_active);
+ case NMEAType::RMCSpeed : return QVariant::fromValue<qreal>(rmcPrivate->m_speed);
+ case NMEAType::RMCAngle : return QVariant::fromValue<qreal>(rmcPrivate->m_angle);
+ case NMEAType::RMCDate : return QVariant::fromValue<QDate>(rmcPrivate->m_date);
+ case NMEAType::RMCVariation : return QVariant::fromValue<qreal>(rmcPrivate->m_variation);
+ default: /* do nothing */ break;
+ }
+ }
+ return QVariant();
+}
+
+void RMC::setValue(NMEAType::Value type, QVariant value)
+{
+ Q_ASSERT(m_private != Q_NULLPTR);
+ if (type >= (NMEAType::Value)NMEAType::NMEAStart && type <= (NMEAType::Value)NMEAType::GeoBaseEnd) {
+ return GeoBase::setValue(type, value);
+ }
+ else {
+ RMCPrivate* rmcPrivate((RMCPrivate*)m_private);
+ switch (type) {
+ case NMEAType::RMCActive : rmcPrivate->m_active = value.toBool(); break;
+ case NMEAType::RMCSpeed : rmcPrivate->m_speed = value.toDouble(); break;
+ case NMEAType::RMCAngle : rmcPrivate->m_angle = value.toDouble(); break;
+ case NMEAType::RMCDate : rmcPrivate->m_date = value.toDate(); break;
+ case NMEAType::RMCVariation : rmcPrivate->m_variation = value.toDouble(); break;
+ default: /* do nothing */ break;
+ }
+ }
+}
+
+RMC::RMC(QStringList data)
+{
+ RMCPrivate* newPrivate = new RMCPrivate;
+ if (data.count() == 13) {
+ QString utcTime(data.at(1));
+ if (utcTime.length() > 6) {
+ newPrivate->m_taken = QTime::fromString(utcTime, "hhmmss.z");
+ }
+ else {
+ newPrivate->m_taken = QTime::fromString(utcTime, "hhmmss");
+ }
+
+ newPrivate->m_active = (data.at(2).compare("A") == 0);
+
+ bool ok(false);
+ qreal position(data.at(3).toDouble(&ok));
+ if (ok) {
+ qreal degrees(qFloor(0.01 * position));
+ newPrivate->m_latitude = (degrees + ((position - (100.0 * degrees)) / 60));
+ if (data.at(4).compare("S", Qt::CaseInsensitive) == 0) {
+ newPrivate->m_latitude *= -1.0;
+ }
+ }
+ else {
+ qWarning("RMC::RMC - Error in latitude parse");
+ }
+ position = data.at(5).toDouble(&ok);
+ if (ok) {
+ qreal degrees(qFloor(0.01 * position));
+ newPrivate->m_longitude = (degrees + ((position - (100.0 * degrees)) / 60));
+ if (data.at(6).compare("W", Qt::CaseInsensitive) == 0) {
+ newPrivate->m_longitude *= -1.0;
+ }
+ }
+ else {
+ qWarning("RMC::RMC - Error in longitude parse");
+ }
+ newPrivate->m_speed = data.at(7).toDouble(&ok);
+ if (!ok) {
+ qWarning("RMC::RMC - Error in speed parse");
+ }
+ newPrivate->m_angle = data.at(8).toDouble(&ok);
+ if (!ok) {
+ qWarning("RMC::RMC - Error in angle parse, data: %s", qPrintable(data.at(8)));
+ }
+ newPrivate->m_date = QDate::fromString(data.at(9), "ddMMyy");
+
+ newPrivate->m_variation = data.at(10).toDouble(&ok);
+ if (!ok) {
+ qWarning("RMC::RMC - Error in variation parse");
+ }
+ if (data.at(11).compare("W", Qt::CaseInsensitive) == 0) {
+ newPrivate->m_variation *= -1.0;
+ }
+ }
+ else {
+ qWarning("RMC::RMC - Error incorrect amount of data %d available!", data.count());
+ }
+ delete m_private;
+ newPrivate->m_type = NMEAType::RMCType;
+ m_private = newPrivate;
+}
diff --git a/CanController/nmea.h b/CanController/nmea.h
new file mode 100644
index 0000000..8df1b63
--- /dev/null
+++ b/CanController/nmea.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef NMEA_H
+#define NMEA_H
+
+#include <QStringList>
+#include <QDateTime>
+#include <QByteArray>
+#include <QList>
+#include <QVariant>
+
+#include "valuetypes.h"
+
+class NMEA
+{
+protected:
+ NMEA();
+
+public:
+ virtual ~NMEA();
+
+ // NOTE: ownership is changed, caller must delete
+ static NMEA* parse(QString data);
+ bool isValid() const;
+ NMEAType::Type type() const;
+ virtual QVariant value(NMEAType::Value type) const;
+ virtual void setValue(NMEAType::Value type, QVariant value);
+
+protected:
+ struct NMEAPrivate* m_private;
+
+};
+
+
+// GeoBase
+
+class GeoBase : public NMEA
+{
+protected:
+ GeoBase();
+
+public:
+ virtual ~GeoBase();
+ virtual QVariant value(NMEAType::Value type) const;
+ virtual void setValue(NMEAType::Value type, QVariant value);
+};
+
+
+// GGA
+
+class GGA : public GeoBase
+{
+public:
+ virtual ~GGA();
+ virtual QVariant value(NMEAType::Value type) const;
+ virtual void setValue(NMEAType::Value type, QVariant value);
+
+private:
+ GGA(QStringList data);
+ friend class NMEA;
+};
+
+
+// RMC
+
+class RMC : public GeoBase
+{
+public:
+ virtual ~RMC();
+ virtual QVariant value(NMEAType::Value type) const;
+ virtual void setValue(NMEAType::Value type, QVariant value);
+
+private:
+ RMC(QStringList data);
+ friend class NMEA;
+};
+
+#endif // NMEA_H
diff --git a/CanController/route.txt b/CanController/route.txt
new file mode 100644
index 0000000..2262763
--- /dev/null
+++ b/CanController/route.txt
@@ -0,0 +1,1188 @@
+$GPGGA,120156,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,120156,A,5232.08,N,1317.6,E,0,200.0,030308,11.2,W,A*22
+$GPGGA,120157,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120157,A,5232.08,N,1317.6,E,0,200.0,030308,11.2,W,A*23
+$GPGGA,120158,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120158,A,5232.08,N,1317.6,E,0,200.0,030308,11.2,W,A*2c
+$GPGGA,120159,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,120159,A,5232.08,N,1317.6,E,0,200.0,030308,11.2,W,A*2d
+$GPGGA,120200,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,120200,A,5232.08,N,1317.6,E,3.9,200.0,030308,11.2,W,A*36
+$GPGGA,120201,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120201,A,5232.08,N,1317.6,E,8.7,197.0,030308,11.2,W,A*3f
+$GPGGA,120202,5232.07,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,120202,A,5232.07,N,1317.6,E,11.7,215.0,030308,11.2,W,A*02
+$GPGGA,120203,5232.07,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120203,A,5232.07,N,1317.59,E,19.4,205.0,030308,11.2,W,A*33
+$GPGGA,120204,5232.06,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120204,A,5232.06,N,1317.59,E,19.9,191.0,030308,11.2,W,A*36
+$GPGGA,120205,5232.05,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120205,A,5232.05,N,1317.59,E,21.4,166.0,030308,11.2,W,A*3a
+$GPGGA,120206,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120206,A,5232.05,N,1317.6,E,19.9,131.0,030308,11.2,W,A*07
+$GPGGA,120207,5232.04,N,1317.61,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120207,A,5232.04,N,1317.61,E,18.5,140.0,030308,11.2,W,A*3d
+$GPGGA,120208,5232.04,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120208,A,5232.04,N,1317.62,E,17.5,133.0,030308,11.2,W,A*3a
+$GPGGA,120209,5232.03,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120209,A,5232.03,N,1317.62,E,17.5,151.0,030308,11.2,W,A*38
+$GPGGA,120210,5232.03,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120210,A,5232.03,N,1317.63,E,9.7,161.0,030308,11.2,W,A*0f
+$GPGGA,120211,5232.02,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120211,A,5232.02,N,1317.63,E,5.8,168.0,030308,11.2,W,A*05
+$GPGGA,120212,5232.02,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120212,A,5232.02,N,1317.63,E,0,166.0,030308,11.2,W,A*1b
+$GPGGA,120213,5232.02,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120213,A,5232.02,N,1317.63,E,0,166.0,030308,11.2,W,A*1a
+$GPGGA,120214,5232.02,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120214,A,5232.02,N,1317.63,E,0,166.0,030308,11.2,W,A*1d
+$GPGGA,120215,5232.01,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120215,A,5232.01,N,1317.64,E,9.7,153.0,030308,11.2,W,A*0e
+$GPGGA,120216,5232,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*64
+$GPRMC,120216,A,5232,N,1317.64,E,19.4,153.0,030308,11.2,W,A*10
+$GPGGA,120217,5232,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*64
+$GPRMC,120217,A,5232,N,1317.65,E,19.4,157.0,030308,11.2,W,A*14
+$GPGGA,120218,5231.99,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120218,A,5231.99,N,1317.65,E,19.9,154.0,030308,11.2,W,A*38
+$GPGGA,120219,5231.99,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120219,A,5231.99,N,1317.66,E,22.4,156.0,030308,11.2,W,A*3d
+$GPGGA,120220,5231.98,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120220,A,5231.98,N,1317.66,E,21.9,150.0,030308,11.2,W,A*3e
+$GPGGA,120221,5231.97,N,1317.67,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120221,A,5231.97,N,1317.67,E,22.4,160.0,030308,11.2,W,A*3c
+$GPGGA,120222,5231.96,N,1317.67,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120222,A,5231.96,N,1317.67,E,23.3,154.0,030308,11.2,W,A*3f
+$GPGGA,120223,5231.96,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120223,A,5231.96,N,1317.68,E,23.3,165.0,030308,11.2,W,A*33
+$GPGGA,120224,5231.95,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120224,A,5231.95,N,1317.68,E,23.3,161.0,030308,11.2,W,A*33
+$GPGGA,120225,5231.94,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120225,A,5231.94,N,1317.68,E,23.3,160.0,030308,11.2,W,A*32
+$GPGGA,120226,5231.94,N,1317.69,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120226,A,5231.94,N,1317.69,E,23.3,155.0,030308,11.2,W,A*36
+$GPGGA,120227,5231.93,N,1317.69,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120227,A,5231.93,N,1317.69,E,23.3,157.0,030308,11.2,W,A*32
+$GPGGA,120228,5231.92,N,1317.7,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120228,A,5231.92,N,1317.7,E,23.3,159.0,030308,11.2,W,A*0a
+$GPGGA,120229,5231.91,N,1317.71,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120229,A,5231.91,N,1317.71,E,23.8,157.0,030308,11.2,W,A*3c
+$GPGGA,120230,5231.9,N,1317.71,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120230,A,5231.9,N,1317.71,E,25.3,158.0,030308,11.2,W,A*07
+$GPGGA,120231,5231.9,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*72
+$GPRMC,120231,A,5231.9,N,1317.72,E,28.2,157.0,030308,11.2,W,A*06
+$GPGGA,120232,5231.89,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120232,A,5231.89,N,1317.72,E,29.2,159.0,030308,11.2,W,A*32
+$GPGGA,120233,5231.88,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120233,A,5231.88,N,1317.72,E,29.6,165.0,030308,11.2,W,A*39
+$GPGGA,120234,5231.87,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120234,A,5231.87,N,1317.73,E,28.7,167.0,030308,11.2,W,A*32
+$GPGGA,120235,5231.86,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120235,A,5231.86,N,1317.73,E,28.2,168.0,030308,11.2,W,A*38
+$GPGGA,120236,5231.85,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120236,A,5231.85,N,1317.73,E,26.7,168.0,030308,11.2,W,A*33
+$GPGGA,120237,5231.84,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120237,A,5231.84,N,1317.74,E,28.2,170.0,030308,11.2,W,A*36
+$GPGGA,120238,5231.83,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120238,A,5231.83,N,1317.74,E,28.7,172.0,030308,11.2,W,A*39
+$GPGGA,120239,5231.82,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120239,A,5231.82,N,1317.74,E,29.2,168.0,030308,11.2,W,A*36
+$GPGGA,120240,5231.81,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120240,A,5231.81,N,1317.75,E,28.7,168.0,030308,11.2,W,A*3e
+$GPGGA,120241,5231.8,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120241,A,5231.8,N,1317.75,E,28.2,167.0,030308,11.2,W,A*04
+$GPGGA,120242,5231.79,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120242,A,5231.79,N,1317.75,E,27.7,170.0,030308,11.2,W,A*3d
+$GPGGA,120243,5231.78,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120243,A,5231.78,N,1317.75,E,27.2,169.0,030308,11.2,W,A*30
+$GPGGA,120244,5231.77,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120244,A,5231.77,N,1317.76,E,26.7,165.0,030308,11.2,W,A*33
+$GPGGA,120245,5231.76,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120245,A,5231.76,N,1317.77,E,26.2,153.0,030308,11.2,W,A*32
+$GPGGA,120246,5231.75,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120246,A,5231.75,N,1317.77,E,26.2,156.0,030308,11.2,W,A*37
+$GPGGA,120247,5231.75,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120247,A,5231.75,N,1317.78,E,26.2,155.0,030308,11.2,W,A*3a
+$GPGGA,120248,5231.74,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120248,A,5231.74,N,1317.78,E,25.8,151.0,030308,11.2,W,A*39
+$GPGGA,120249,5231.74,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120249,A,5231.74,N,1317.79,E,23.8,150.0,030308,11.2,W,A*3e
+$GPGGA,120250,5231.73,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120250,A,5231.73,N,1317.79,E,21.9,166.0,030308,11.2,W,A*37
+$GPGGA,120251,5231.72,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120251,A,5231.72,N,1317.79,E,23.3,167.0,030308,11.2,W,A*3e
+$GPGGA,120252,5231.71,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,120252,A,5231.71,N,1317.8,E,24.8,173.0,030308,11.2,W,A*01
+$GPGGA,120253,5231.7,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120253,A,5231.7,N,1317.8,E,24.8,170.0,030308,11.2,W,A*32
+$GPGGA,120254,5231.69,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120254,A,5231.69,N,1317.8,E,24.8,171.0,030308,11.2,W,A*0c
+$GPGGA,120255,5231.68,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120255,A,5231.68,N,1317.8,E,24.8,166.0,030308,11.2,W,A*0a
+$GPGGA,120256,5231.68,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120256,A,5231.68,N,1317.81,E,24.9,167.0,030308,11.2,W,A*38
+$GPGGA,120257,5231.67,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120257,A,5231.67,N,1317.81,E,28.2,165.0,030308,11.2,W,A*33
+$GPGGA,120258,5231.66,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120258,A,5231.66,N,1317.81,E,30.1,165.0,030308,11.2,W,A*37
+$GPGGA,120259,5231.65,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120259,A,5231.65,N,1317.82,E,31.6,168.0,030308,11.2,W,A*3d
+$GPGGA,120300,5231.64,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120300,A,5231.64,N,1317.82,E,33.0,167.0,030308,11.2,W,A*3a
+$GPGGA,120301,5231.63,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120301,A,5231.63,N,1317.82,E,33.0,169.0,030308,11.2,W,A*32
+$GPGGA,120302,5231.62,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120302,A,5231.62,N,1317.83,E,33.0,171.0,030308,11.2,W,A*38
+$GPGGA,120303,5231.61,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120303,A,5231.61,N,1317.83,E,33.0,168.0,030308,11.2,W,A*32
+$GPGGA,120304,5231.6,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,120304,A,5231.6,N,1317.83,E,33.0,166.0,030308,11.2,W,A*0a
+$GPGGA,120305,5231.59,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120305,A,5231.59,N,1317.84,E,34.5,169.0,030308,11.2,W,A*3b
+$GPGGA,120306,5231.58,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120306,A,5231.58,N,1317.84,E,34.5,165.0,030308,11.2,W,A*35
+$GPGGA,120307,5231.57,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120307,A,5231.57,N,1317.84,E,35.5,168.0,030308,11.2,W,A*37
+$GPGGA,120308,5231.56,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120308,A,5231.56,N,1317.85,E,36.0,170.0,030308,11.2,W,A*37
+$GPGGA,120309,5231.55,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120309,A,5231.55,N,1317.85,E,35.5,174.0,030308,11.2,W,A*37
+$GPGGA,120310,5231.54,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120310,A,5231.54,N,1317.85,E,34.0,168.0,030308,11.2,W,A*37
+$GPGGA,120311,5231.53,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120311,A,5231.53,N,1317.85,E,34.0,174.0,030308,11.2,W,A*3c
+$GPGGA,120312,5231.52,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120312,A,5231.52,N,1317.85,E,33.0,176.0,030308,11.2,W,A*3b
+$GPGGA,120313,5231.51,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120313,A,5231.51,N,1317.86,E,32.6,173.0,030308,11.2,W,A*38
+$GPGGA,120314,5231.5,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120314,A,5231.5,N,1317.86,E,31.6,168.0,030308,11.2,W,A*07
+$GPGGA,120315,5231.49,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120315,A,5231.49,N,1317.86,E,29.6,166.0,030308,11.2,W,A*39
+$GPGGA,120316,5231.49,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120316,A,5231.49,N,1317.87,E,29.6,165.0,030308,11.2,W,A*38
+$GPGGA,120317,5231.48,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120317,A,5231.48,N,1317.87,E,29.6,152.0,030308,11.2,W,A*3c
+$GPGGA,120318,5231.47,N,1317.88,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120318,A,5231.47,N,1317.88,E,30.6,155.0,030308,11.2,W,A*3c
+$GPGGA,120319,5231.46,N,1317.89,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120319,A,5231.46,N,1317.89,E,31.6,146.0,030308,11.2,W,A*3e
+$GPGGA,120320,5231.45,N,1317.9,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,120320,A,5231.45,N,1317.9,E,31.6,140.0,030308,11.2,W,A*09
+$GPGGA,120321,5231.44,N,1317.91,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120321,A,5231.44,N,1317.91,E,31.6,145.0,030308,11.2,W,A*3d
+$GPGGA,120322,5231.44,N,1317.92,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120322,A,5231.44,N,1317.92,E,31.6,140.0,030308,11.2,W,A*38
+$GPGGA,120323,5231.43,N,1317.93,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120323,A,5231.43,N,1317.93,E,31.6,143.0,030308,11.2,W,A*3c
+$GPGGA,120324,5231.42,N,1317.94,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120324,A,5231.42,N,1317.94,E,31.8,144.0,030308,11.2,W,A*34
+$GPGGA,120325,5231.41,N,1317.95,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120325,A,5231.41,N,1317.95,E,32.1,143.0,030308,11.2,W,A*3a
+$GPGGA,120326,5231.4,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*72
+$GPRMC,120326,A,5231.4,N,1317.96,E,31.1,141.0,030308,11.2,W,A*0a
+$GPGGA,120327,5231.39,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120327,A,5231.39,N,1317.97,E,35.0,143.0,030308,11.2,W,A*33
+$GPGGA,120328,5231.39,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120328,A,5231.39,N,1317.98,E,35.0,148.0,030308,11.2,W,A*38
+$GPGGA,120329,5231.38,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120329,A,5231.38,N,1317.98,E,35.0,143.0,030308,11.2,W,A*33
+$GPGGA,120330,5231.38,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120330,A,5231.38,N,1317.99,E,25.3,142.0,030308,11.2,W,A*39
+$GPGGA,120331,5231.37,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*6a
+$GPRMC,120331,A,5231.37,N,1318,E,15.6,141.0,030308,11.2,W,A*13
+$GPGGA,120332,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120332,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*10
+$GPGGA,120333,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120333,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*11
+$GPGGA,120334,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120334,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*16
+$GPGGA,120335,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120335,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*17
+$GPGGA,120336,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120336,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*14
+$GPGGA,120337,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120337,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*15
+$GPGGA,120338,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120338,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*1a
+$GPGGA,120339,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120339,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*1b
+$GPGGA,120340,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120340,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*15
+$GPGGA,120341,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120341,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*14
+$GPGGA,120342,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120342,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*17
+$GPGGA,120343,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120343,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*16
+$GPGGA,120344,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120344,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*11
+$GPGGA,120345,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120345,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*10
+$GPGGA,120346,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120346,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*13
+$GPGGA,120347,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120347,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*12
+$GPGGA,120348,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120348,A,5231.36,N,1318.01,E,0,143.0,030308,11.2,W,A*1d
+$GPGGA,120349,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120349,A,5231.36,N,1318.01,E,10.2,156.0,030308,11.2,W,A*35
+$GPGGA,120350,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120350,A,5231.36,N,1318.01,E,17.5,149.0,030308,11.2,W,A*33
+$GPGGA,120351,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120351,A,5231.35,N,1318.02,E,23.3,148.0,030308,11.2,W,A*32
+$GPGGA,120352,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120352,A,5231.35,N,1318.02,E,29.2,177.0,030308,11.2,W,A*36
+$GPGGA,120353,5231.34,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120353,A,5231.34,N,1318.02,E,29.2,189.0,030308,11.2,W,A*37
+$GPGGA,120354,5231.34,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120354,A,5231.34,N,1318.01,E,29.2,198.0,030308,11.2,W,A*33
+$GPGGA,120355,5231.33,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120355,A,5231.33,N,1318.01,E,29.2,192.0,030308,11.2,W,A*3f
+$GPGGA,120356,5231.32,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120356,A,5231.32,N,1318.01,E,35.0,196.0,030308,11.2,W,A*36
+$GPGGA,120357,5231.31,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*6c
+$GPRMC,120357,A,5231.31,N,1318,E,35.0,202.0,030308,11.2,W,A*15
+$GPGGA,120358,5231.3,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*52
+$GPRMC,120358,A,5231.3,N,1318,E,27.2,201.0,030308,11.2,W,A*29
+$GPGGA,120359,5231.3,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*72
+$GPRMC,120359,A,5231.3,N,1317.99,E,28.7,196.0,030308,11.2,W,A*0e
+$GPGGA,120400,5231.29,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120400,A,5231.29,N,1317.99,E,29.6,200.0,030308,11.2,W,A*31
+$GPGGA,120401,5231.28,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120401,A,5231.28,N,1317.98,E,30.6,201.0,030308,11.2,W,A*39
+$GPGGA,120402,5231.27,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120402,A,5231.27,N,1317.98,E,30.1,201.0,030308,11.2,W,A*32
+$GPGGA,120403,5231.26,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120403,A,5231.26,N,1317.97,E,29.2,198.0,030308,11.2,W,A*35
+$GPGGA,120404,5231.25,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120404,A,5231.25,N,1317.96,E,25.8,199.0,030308,11.2,W,A*37
+$GPGGA,120405,5231.24,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120405,A,5231.24,N,1317.96,E,23.8,188.0,030308,11.2,W,A*31
+$GPGGA,120406,5231.23,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120406,A,5231.23,N,1317.96,E,22.4,177.0,030308,11.2,W,A*38
+$GPGGA,120407,5231.22,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120407,A,5231.22,N,1317.96,E,19.9,174.0,030308,11.2,W,A*3e
+$GPGGA,120408,5231.22,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120408,A,5231.22,N,1317.97,E,11.7,170.0,030308,11.2,W,A*32
+$GPGGA,120409,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120409,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*29
+$GPGGA,120410,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,120410,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*21
+$GPGGA,120411,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*76
+$GPRMC,120411,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*20
+$GPGGA,120412,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,120412,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*23
+$GPGGA,120413,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,120413,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*22
+$GPGGA,120414,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120414,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*25
+$GPGGA,120415,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*72
+$GPRMC,120415,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*24
+$GPGGA,120416,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,120416,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*27
+$GPGGA,120417,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120417,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*26
+$GPGGA,120418,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120418,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*29
+$GPGGA,120419,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,120419,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*28
+$GPGGA,120420,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,120420,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*22
+$GPGGA,120421,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,120421,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*23
+$GPGGA,120422,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*76
+$GPRMC,120422,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*20
+$GPGGA,120423,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,120423,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*21
+$GPGGA,120424,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120424,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*26
+$GPGGA,120425,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,120425,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*27
+$GPGGA,120426,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*72
+$GPRMC,120426,A,5231.2,N,1317.97,E,0,171.0,030308,11.2,W,A*24
+$GPGGA,120427,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120427,A,5231.2,N,1317.97,E,9.7,149.0,030308,11.2,W,A*3e
+$GPGGA,120428,5231.2,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,120428,A,5231.2,N,1317.97,E,13.6,171.0,030308,11.2,W,A*00
+$GPGGA,120429,5231.19,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120429,A,5231.19,N,1317.97,E,13.6,172.0,030308,11.2,W,A*38
+$GPGGA,120430,5231.19,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120430,A,5231.19,N,1317.97,E,14.6,177.0,030308,11.2,W,A*32
+$GPGGA,120431,5231.18,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120431,A,5231.18,N,1317.98,E,17.5,162.0,030308,11.2,W,A*39
+$GPGGA,120432,5231.18,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120432,A,5231.18,N,1317.98,E,23.3,158.0,030308,11.2,W,A*32
+$GPGGA,120433,5231.17,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120433,A,5231.17,N,1317.98,E,23.3,146.0,030308,11.2,W,A*33
+$GPGGA,120434,5231.17,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120434,A,5231.17,N,1317.99,E,23.3,127.0,030308,11.2,W,A*32
+$GPGGA,120435,5231.17,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*6b
+$GPRMC,120435,A,5231.17,N,1318,E,23.3,121.0,030308,11.2,W,A*14
+$GPGGA,120436,5231.16,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120436,A,5231.16,N,1318.01,E,24.8,120.0,030308,11.2,W,A*34
+$GPGGA,120437,5231.16,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120437,A,5231.16,N,1318.02,E,26.7,118.0,030308,11.2,W,A*30
+$GPGGA,120438,5231.16,N,1318.03,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120438,A,5231.16,N,1318.03,E,28.2,120.0,030308,11.2,W,A*3e
+$GPGGA,120439,5231.15,N,1318.04,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120439,A,5231.15,N,1318.04,E,30.1,120.0,030308,11.2,W,A*31
+$GPGGA,120440,5231.15,N,1318.05,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120440,A,5231.15,N,1318.05,E,31.6,122.0,030308,11.2,W,A*3a
+$GPGGA,120441,5231.14,N,1318.07,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120441,A,5231.14,N,1318.07,E,32.6,119.0,030308,11.2,W,A*33
+$GPGGA,120442,5231.14,N,1318.08,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120442,A,5231.14,N,1318.08,E,33.5,117.0,030308,11.2,W,A*33
+$GPGGA,120443,5231.13,N,1318.1,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,120443,A,5231.13,N,1318.1,E,34.5,118.0,030308,11.2,W,A*04
+$GPGGA,120444,5231.13,N,1318.11,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120444,A,5231.13,N,1318.11,E,35.5,118.0,030308,11.2,W,A*33
+$GPGGA,120445,5231.12,N,1318.12,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120445,A,5231.12,N,1318.12,E,36.4,118.0,030308,11.2,W,A*32
+$GPGGA,120446,5231.12,N,1318.14,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120446,A,5231.12,N,1318.14,E,36.4,115.0,030308,11.2,W,A*3a
+$GPGGA,120447,5231.12,N,1318.15,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120447,A,5231.12,N,1318.15,E,36.4,121.0,030308,11.2,W,A*3d
+$GPGGA,120448,5231.11,N,1318.17,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120448,A,5231.11,N,1318.17,E,36.4,116.0,030308,11.2,W,A*37
+$GPGGA,120449,5231.11,N,1318.18,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120449,A,5231.11,N,1318.18,E,35.5,116.0,030308,11.2,W,A*3b
+$GPGGA,120450,5231.1,N,1318.2,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120450,A,5231.1,N,1318.2,E,35.0,117.0,030308,11.2,W,A*3d
+$GPGGA,120451,5231.1,N,1318.21,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120451,A,5231.1,N,1318.21,E,34.5,115.0,030308,11.2,W,A*0b
+$GPGGA,120452,5231.09,N,1318.22,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120452,A,5231.09,N,1318.22,E,33.5,119.0,030308,11.2,W,A*38
+$GPGGA,120453,5231.09,N,1318.24,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120453,A,5231.09,N,1318.24,E,32.6,115.0,030308,11.2,W,A*31
+$GPGGA,120454,5231.08,N,1318.25,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120454,A,5231.08,N,1318.25,E,32.1,115.0,030308,11.2,W,A*31
+$GPGGA,120455,5231.08,N,1318.26,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120455,A,5231.08,N,1318.26,E,32.1,115.0,030308,11.2,W,A*33
+$GPGGA,120456,5231.08,N,1318.28,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120456,A,5231.08,N,1318.28,E,31.1,115.0,030308,11.2,W,A*3d
+$GPGGA,120457,5231.07,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120457,A,5231.07,N,1318.29,E,31.1,114.0,030308,11.2,W,A*33
+$GPGGA,120458,5231.07,N,1318.3,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,120458,A,5231.07,N,1318.3,E,31.1,117.0,030308,11.2,W,A*07
+$GPGGA,120459,5231.07,N,1318.31,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120459,A,5231.07,N,1318.31,E,31.6,116.0,030308,11.2,W,A*31
+$GPGGA,120500,5231.06,N,1318.33,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120500,A,5231.06,N,1318.33,E,32.1,120.0,030308,11.2,W,A*3e
+$GPGGA,120501,5231.06,N,1318.34,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120501,A,5231.06,N,1318.34,E,32.6,124.0,030308,11.2,W,A*3b
+$GPGGA,120502,5231.05,N,1318.35,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120502,A,5231.05,N,1318.35,E,33.0,124.0,030308,11.2,W,A*3d
+$GPGGA,120503,5231.05,N,1318.37,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120503,A,5231.05,N,1318.37,E,34.0,107.0,030308,11.2,W,A*38
+$GPGGA,120504,5231.04,N,1318.38,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120504,A,5231.04,N,1318.38,E,33.5,114.0,030308,11.2,W,A*31
+$GPGGA,120505,5231.04,N,1318.39,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120505,A,5231.04,N,1318.39,E,34.0,116.0,030308,11.2,W,A*31
+$GPGGA,120506,5231.04,N,1318.41,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120506,A,5231.04,N,1318.41,E,34.5,112.0,030308,11.2,W,A*3c
+$GPGGA,120507,5231.03,N,1318.42,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120507,A,5231.03,N,1318.42,E,35.0,116.0,030308,11.2,W,A*39
+$GPGGA,120508,5231.03,N,1318.44,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120508,A,5231.03,N,1318.44,E,35.5,120.0,030308,11.2,W,A*30
+$GPGGA,120509,5231.02,N,1318.45,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120509,A,5231.02,N,1318.45,E,35.5,120.0,030308,11.2,W,A*31
+$GPGGA,120510,5231.02,N,1318.47,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120510,A,5231.02,N,1318.47,E,36.4,120.0,030308,11.2,W,A*39
+$GPGGA,120511,5231.01,N,1318.48,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120511,A,5231.01,N,1318.48,E,36.0,118.0,030308,11.2,W,A*3b
+$GPGGA,120512,5231.01,N,1318.5,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120512,A,5231.01,N,1318.5,E,36.4,103.0,030308,11.2,W,A*0f
+$GPGGA,120513,5231.01,N,1318.51,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120513,A,5231.01,N,1318.51,E,36.4,115.0,030308,11.2,W,A*38
+$GPGGA,120514,5231,N,1318.53,E,1,07,1.3,50.6,M,39.2,M,,*69
+$GPRMC,120514,A,5231,N,1318.53,E,36.4,125.0,030308,11.2,W,A*11
+$GPGGA,120515,5231,N,1318.54,E,1,07,1.3,50.6,M,39.2,M,,*6f
+$GPRMC,120515,A,5231,N,1318.54,E,36.0,102.0,030308,11.2,W,A*16
+$GPGGA,120516,5230.99,N,1318.56,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120516,A,5230.99,N,1318.56,E,35.5,110.0,030308,11.2,W,A*3d
+$GPGGA,120517,5230.99,N,1318.57,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120517,A,5230.99,N,1318.57,E,34.0,125.0,030308,11.2,W,A*3f
+$GPGGA,120518,5230.98,N,1318.58,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120518,A,5230.98,N,1318.58,E,33.5,127.0,030308,11.2,W,A*3e
+$GPGGA,120519,5230.98,N,1318.6,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120519,A,5230.98,N,1318.6,E,33.5,125.0,030308,11.2,W,A*06
+$GPGGA,120520,5230.97,N,1318.61,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120520,A,5230.97,N,1318.61,E,33.0,134.0,030308,11.2,W,A*37
+$GPGGA,120521,5230.96,N,1318.63,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120521,A,5230.96,N,1318.63,E,32.6,116.0,030308,11.2,W,A*32
+$GPGGA,120522,5230.96,N,1318.64,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120522,A,5230.96,N,1318.64,E,31.6,116.0,030308,11.2,W,A*35
+$GPGGA,120523,5230.95,N,1318.67,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120523,A,5230.95,N,1318.67,E,31.6,120.0,030308,11.2,W,A*31
+$GPGGA,120524,5230.95,N,1318.68,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120524,A,5230.95,N,1318.68,E,33.0,114.0,030308,11.2,W,A*3a
+$GPGGA,120525,5230.94,N,1318.7,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,120525,A,5230.94,N,1318.7,E,33.0,107.0,030308,11.2,W,A*01
+$GPGGA,120526,5230.94,N,1318.71,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120526,A,5230.94,N,1318.71,E,33.0,111.0,030308,11.2,W,A*34
+$GPGGA,120527,5230.93,N,1318.74,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120527,A,5230.93,N,1318.74,E,33.0,122.0,030308,11.2,W,A*37
+$GPGGA,120528,5230.93,N,1318.75,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120528,A,5230.93,N,1318.75,E,33.0,102.0,030308,11.2,W,A*3b
+$GPGGA,120529,5230.92,N,1318.77,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120529,A,5230.92,N,1318.77,E,33.5,116.0,030308,11.2,W,A*39
+$GPGGA,120530,5230.92,N,1318.78,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120530,A,5230.92,N,1318.78,E,33.5,117.0,030308,11.2,W,A*3f
+$GPGGA,120531,5230.91,N,1318.79,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120531,A,5230.91,N,1318.79,E,33.0,126.0,030308,11.2,W,A*3b
+$GPGGA,120532,5230.91,N,1318.8,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,120532,A,5230.91,N,1318.8,E,33.0,115.0,030308,11.2,W,A*0e
+$GPGGA,120533,5230.91,N,1318.82,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120533,A,5230.91,N,1318.82,E,33.0,117.0,030308,11.2,W,A*3f
+$GPGGA,120534,5230.9,N,1318.83,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120534,A,5230.9,N,1318.83,E,33.0,118.0,030308,11.2,W,A*07
+$GPGGA,120535,5230.9,N,1318.84,E,1,07,1.3,50.6,M,39.2,M,,*76
+$GPRMC,120535,A,5230.9,N,1318.84,E,31.1,119.0,030308,11.2,W,A*03
+$GPGGA,120536,5230.89,N,1318.86,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120536,A,5230.89,N,1318.86,E,28.7,116.0,030308,11.2,W,A*3b
+$GPGGA,120537,5230.89,N,1318.87,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120537,A,5230.89,N,1318.87,E,25.3,110.0,030308,11.2,W,A*34
+$GPGGA,120538,5230.89,N,1318.88,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120538,A,5230.89,N,1318.88,E,22.4,101.0,030308,11.2,W,A*34
+$GPGGA,120539,5230.88,N,1318.88,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120539,A,5230.88,N,1318.88,E,18.0,153.0,030308,11.2,W,A*3e
+$GPGGA,120540,5230.88,N,1318.88,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120540,A,5230.88,N,1318.88,E,2.9,142.0,030308,11.2,W,A*02
+$GPGGA,120541,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120541,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2a
+$GPGGA,120542,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120542,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*29
+$GPGGA,120543,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120543,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*28
+$GPGGA,120544,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120544,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2f
+$GPGGA,120545,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120545,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2e
+$GPGGA,120546,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120546,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2d
+$GPGGA,120547,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120547,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2c
+$GPGGA,120548,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120548,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*23
+$GPGGA,120549,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120549,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*22
+$GPGGA,120550,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120550,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2a
+$GPGGA,120551,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120551,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2b
+$GPGGA,120552,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120552,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*28
+$GPGGA,120553,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120553,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*29
+$GPGGA,120554,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120554,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2e
+$GPGGA,120555,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120555,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2f
+$GPGGA,120556,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120556,A,5230.88,N,1318.89,E,0,93.0,030308,11.2,W,A*2c
+$GPGGA,120557,5230.88,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120557,A,5230.88,N,1318.89,E,5.3,124.0,030308,11.2,W,A*08
+$GPGGA,120558,5230.88,N,1318.9,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,120558,A,5230.88,N,1318.9,E,17.5,133.0,030308,11.2,W,A*0c
+$GPGGA,120559,5230.88,N,1318.9,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120559,A,5230.88,N,1318.9,E,23.3,117.0,030308,11.2,W,A*0a
+$GPGGA,120600,5230.87,N,1318.92,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120600,A,5230.87,N,1318.92,E,25.3,114.0,030308,11.2,W,A*3d
+$GPGGA,120601,5230.87,N,1318.93,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120601,A,5230.87,N,1318.93,E,31.1,113.0,030308,11.2,W,A*3d
+$GPGGA,120602,5230.87,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120602,A,5230.87,N,1318.94,E,35.0,104.0,030308,11.2,W,A*3a
+$GPGGA,120603,5230.86,N,1318.95,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120603,A,5230.86,N,1318.95,E,38.9,118.0,030308,11.2,W,A*32
+$GPGGA,120604,5230.86,N,1318.96,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120604,A,5230.86,N,1318.96,E,31.1,109.0,030308,11.2,W,A*37
+$GPGGA,120605,5230.86,N,1318.98,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120605,A,5230.86,N,1318.98,E,30.6,116.0,030308,11.2,W,A*30
+$GPGGA,120606,5230.85,N,1318.99,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120606,A,5230.85,N,1318.99,E,30.6,107.0,030308,11.2,W,A*31
+$GPGGA,120607,5230.85,N,1319,E,1,07,1.3,50.6,M,39.2,M,,*63
+$GPRMC,120607,A,5230.85,N,1319,E,30.1,133.0,030308,11.2,W,A*1f
+$GPGGA,120608,5230.84,N,1319.01,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120608,A,5230.84,N,1319.01,E,30.1,126.0,030308,11.2,W,A*3a
+$GPGGA,120609,5230.84,N,1319.03,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120609,A,5230.84,N,1319.03,E,31.6,119.0,030308,11.2,W,A*33
+$GPGGA,120610,5230.83,N,1319.05,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120610,A,5230.83,N,1319.05,E,31.6,121.0,030308,11.2,W,A*31
+$GPGGA,120611,5230.83,N,1319.06,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120611,A,5230.83,N,1319.06,E,31.6,109.0,030308,11.2,W,A*39
+$GPGGA,120612,5230.83,N,1319.08,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120612,A,5230.83,N,1319.08,E,32.1,94.0,030308,11.2,W,A*05
+$GPGGA,120613,5230.83,N,1319.09,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120613,A,5230.83,N,1319.09,E,32.6,101.0,030308,11.2,W,A*3f
+$GPGGA,120614,5230.82,N,1319.11,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120614,A,5230.82,N,1319.11,E,33.0,94.0,030308,11.2,W,A*0a
+$GPGGA,120615,5230.82,N,1319.12,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120615,A,5230.82,N,1319.12,E,33.0,103.0,030308,11.2,W,A*37
+$GPGGA,120616,5230.82,N,1319.14,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120616,A,5230.82,N,1319.14,E,33.0,100.0,030308,11.2,W,A*31
+$GPGGA,120617,5230.82,N,1319.15,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120617,A,5230.82,N,1319.15,E,32.1,94.0,030308,11.2,W,A*0d
+$GPGGA,120618,5230.81,N,1319.18,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120618,A,5230.81,N,1319.18,E,32.1,115.0,030308,11.2,W,A*34
+$GPGGA,120619,5230.81,N,1319.19,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120619,A,5230.81,N,1319.19,E,30.1,113.0,030308,11.2,W,A*30
+$GPGGA,120620,5230.81,N,1319.2,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,120620,A,5230.81,N,1319.2,E,28.2,107.0,030308,11.2,W,A*0f
+$GPGGA,120621,5230.8,N,1319.21,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120621,A,5230.8,N,1319.21,E,25.3,107.0,030308,11.2,W,A*02
+$GPGGA,120622,5230.8,N,1319.22,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120622,A,5230.8,N,1319.22,E,21.4,117.0,030308,11.2,W,A*00
+$GPGGA,120623,5230.8,N,1319.23,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120623,A,5230.8,N,1319.23,E,0,116.0,030308,11.2,W,A*28
+$GPGGA,120624,5230.8,N,1319.23,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,120624,A,5230.8,N,1319.23,E,0,121.0,030308,11.2,W,A*2b
+$GPGGA,120625,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,120625,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*28
+$GPGGA,120626,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*7d
+$GPRMC,120626,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*2b
+$GPGGA,120627,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,120627,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*2a
+$GPGGA,120628,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120628,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*25
+$GPGGA,120629,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*72
+$GPRMC,120629,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*24
+$GPGGA,120630,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120630,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*2c
+$GPGGA,120631,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*7b
+$GPRMC,120631,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*2d
+$GPGGA,120632,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,120632,A,5230.8,N,1319.24,E,0,117.0,030308,11.2,W,A*2e
+$GPGGA,120633,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120633,A,5230.79,N,1319.25,E,1.9,125.0,030308,11.2,W,A*0f
+$GPGGA,120634,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120634,A,5230.79,N,1319.25,E,11.7,139.0,030308,11.2,W,A*3a
+$GPGGA,120635,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120635,A,5230.79,N,1319.25,E,11.7,157.0,030308,11.2,W,A*33
+$GPGGA,120636,5230.78,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120636,A,5230.78,N,1319.26,E,19.4,163.0,030308,11.2,W,A*3e
+$GPGGA,120637,5230.77,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120637,A,5230.77,N,1319.25,E,20.4,196.0,030308,11.2,W,A*33
+$GPGGA,120638,5230.77,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120638,A,5230.77,N,1319.25,E,19.4,200.0,030308,11.2,W,A*3a
+$GPGGA,120639,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120639,A,5230.76,N,1319.25,E,20.4,183.0,030308,11.2,W,A*38
+$GPGGA,120640,5230.75,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120640,A,5230.75,N,1319.25,E,20.4,175.0,030308,11.2,W,A*3c
+$GPGGA,120641,5230.74,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120641,A,5230.74,N,1319.25,E,21.9,163.0,030308,11.2,W,A*37
+$GPGGA,120642,5230.74,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120642,A,5230.74,N,1319.26,E,22.8,155.0,030308,11.2,W,A*30
+$GPGGA,120643,5230.73,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120643,A,5230.73,N,1319.26,E,22.8,144.0,030308,11.2,W,A*36
+$GPGGA,120644,5230.72,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120644,A,5230.72,N,1319.27,E,23.8,139.0,030308,11.2,W,A*3a
+$GPGGA,120645,5230.73,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120645,A,5230.73,N,1319.36,E,24.7,85.0,030308,11.2,W,A*04
+$GPGGA,120646,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120646,A,5230.74,N,1319.37,E,25.8,26.0,030308,11.2,W,A*06
+$GPGGA,120647,5230.75,N,1319.38,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120647,A,5230.75,N,1319.38,E,24.8,18.0,030308,11.2,W,A*05
+$GPGGA,120648,5230.76,N,1319.38,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120648,A,5230.76,N,1319.38,E,24.3,351.0,030308,11.2,W,A*3c
+$GPGGA,120649,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120649,A,5230.76,N,1319.37,E,24.8,344.0,030308,11.2,W,A*3d
+$GPGGA,120650,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120650,A,5230.77,N,1319.37,E,25.8,342.0,030308,11.2,W,A*33
+$GPGGA,120651,5230.78,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120651,A,5230.78,N,1319.36,E,26.7,323.0,030308,11.2,W,A*37
+$GPGGA,120652,5230.78,N,1319.35,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120652,A,5230.78,N,1319.35,E,26.7,313.0,030308,11.2,W,A*34
+$GPGGA,120653,5230.79,N,1319.34,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120653,A,5230.79,N,1319.34,E,27.7,302.0,030308,11.2,W,A*34
+$GPGGA,120654,5230.79,N,1319.33,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120654,A,5230.79,N,1319.33,E,27.6,271.0,030308,11.2,W,A*30
+$GPGGA,120655,5230.79,N,1319.32,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120655,A,5230.79,N,1319.32,E,27.4,278.0,030308,11.2,W,A*3b
+$GPGGA,120656,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,120656,A,5230.79,N,1319.3,E,27.2,274.0,030308,11.2,W,A*00
+$GPGGA,120657,5230.79,N,1319.29,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120657,A,5230.79,N,1319.29,E,26.2,274.0,030308,11.2,W,A*38
+$GPGGA,120658,5230.79,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120658,A,5230.79,N,1319.28,E,25.8,284.0,030308,11.2,W,A*30
+$GPGGA,120659,5230.79,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120659,A,5230.79,N,1319.27,E,26.7,292.0,030308,11.2,W,A*35
+$GPGGA,120700,5230.8,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120700,A,5230.8,N,1319.26,E,28.2,299.0,030308,11.2,W,A*0f
+$GPGGA,120701,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,120701,A,5230.8,N,1319.24,E,29.6,294.0,030308,11.2,W,A*04
+$GPGGA,120702,5230.8,N,1319.23,E,1,07,1.3,50.6,M,39.2,M,,*7d
+$GPRMC,120702,A,5230.8,N,1319.23,E,30.6,294.0,030308,11.2,W,A*08
+$GPGGA,120703,5230.81,N,1319.22,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120703,A,5230.81,N,1319.22,E,33.0,295.0,030308,11.2,W,A*3d
+$GPGGA,120704,5230.81,N,1319.2,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,120704,A,5230.81,N,1319.2,E,34.0,291.0,030308,11.2,W,A*0b
+$GPGGA,120705,5230.82,N,1319.19,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120705,A,5230.82,N,1319.19,E,35.0,290.0,030308,11.2,W,A*33
+$GPGGA,120706,5230.82,N,1319.17,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120706,A,5230.82,N,1319.17,E,35.0,281.0,030308,11.2,W,A*3e
+$GPGGA,120707,5230.82,N,1319.16,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120707,A,5230.82,N,1319.16,E,34.5,290.0,030308,11.2,W,A*3a
+$GPGGA,120708,5230.82,N,1319.14,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120708,A,5230.82,N,1319.14,E,34.0,283.0,030308,11.2,W,A*30
+$GPGGA,120709,5230.83,N,1319.13,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120709,A,5230.83,N,1319.13,E,33.5,282.0,030308,11.2,W,A*34
+$GPGGA,120710,5230.83,N,1319.11,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120710,A,5230.83,N,1319.11,E,31.6,291.0,030308,11.2,W,A*3d
+$GPGGA,120711,5230.83,N,1319.1,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,120711,A,5230.83,N,1319.1,E,31.6,276.0,030308,11.2,W,A*04
+$GPGGA,120712,5230.83,N,1319.09,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120712,A,5230.83,N,1319.09,E,31.1,283.0,030308,11.2,W,A*32
+$GPGGA,120713,5230.83,N,1319.07,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120713,A,5230.83,N,1319.07,E,31.6,285.0,030308,11.2,W,A*3c
+$GPGGA,120714,5230.84,N,1319.06,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120714,A,5230.84,N,1319.06,E,32.1,288.0,030308,11.2,W,A*34
+$GPGGA,120715,5230.84,N,1319.04,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120715,A,5230.84,N,1319.04,E,33.0,294.0,030308,11.2,W,A*3a
+$GPGGA,120716,5230.85,N,1319.03,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120716,A,5230.85,N,1319.03,E,33.0,297.0,030308,11.2,W,A*3c
+$GPGGA,120717,5230.85,N,1319.02,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120717,A,5230.85,N,1319.02,E,32.6,293.0,030308,11.2,W,A*3f
+$GPGGA,120718,5230.85,N,1319,E,1,07,1.3,50.6,M,39.2,M,,*6c
+$GPRMC,120718,A,5230.85,N,1319,E,31.1,295.0,030308,11.2,W,A*1e
+$GPGGA,120719,5230.86,N,1318.99,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120719,A,5230.86,N,1318.99,E,29.2,296.0,030308,11.2,W,A*3a
+$GPGGA,120720,5230.86,N,1318.98,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120720,A,5230.86,N,1318.98,E,27.7,301.0,030308,11.2,W,A*35
+$GPGGA,120721,5230.86,N,1318.97,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120721,A,5230.86,N,1318.97,E,24.8,292.0,030308,11.2,W,A*3c
+$GPGGA,120722,5230.87,N,1318.96,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120722,A,5230.87,N,1318.96,E,21.9,302.0,030308,11.2,W,A*33
+$GPGGA,120723,5230.87,N,1318.95,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120723,A,5230.87,N,1318.95,E,11.7,293.0,030308,11.2,W,A*35
+$GPGGA,120724,5230.87,N,1318.95,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120724,A,5230.87,N,1318.95,E,7.8,300.0,030308,11.2,W,A*01
+$GPGGA,120725,5230.87,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120725,A,5230.87,N,1318.94,E,3.9,298.0,030308,11.2,W,A*04
+$GPGGA,120726,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120726,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*19
+$GPGGA,120727,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120727,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*18
+$GPGGA,120728,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120728,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*17
+$GPGGA,120729,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120729,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*16
+$GPGGA,120730,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120730,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*1e
+$GPGGA,120731,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120731,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*1f
+$GPGGA,120732,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120732,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*1c
+$GPGGA,120733,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120733,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*1d
+$GPGGA,120734,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120734,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*1a
+$GPGGA,120735,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120735,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*1b
+$GPGGA,120736,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120736,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*18
+$GPGGA,120737,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120737,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*19
+$GPGGA,120738,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120738,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*16
+$GPGGA,120739,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120739,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*17
+$GPGGA,120740,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120740,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*19
+$GPGGA,120741,5230.88,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120741,A,5230.88,N,1318.94,E,0,305.0,030308,11.2,W,A*18
+$GPGGA,120742,5230.88,N,1318.93,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120742,A,5230.88,N,1318.93,E,1.0,295.0,030308,11.2,W,A*0b
+$GPGGA,120743,5230.88,N,1318.93,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120743,A,5230.88,N,1318.93,E,3.9,314.0,030308,11.2,W,A*09
+$GPGGA,120744,5230.88,N,1318.93,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120744,A,5230.88,N,1318.93,E,11.7,296.0,030308,11.2,W,A*38
+$GPGGA,120745,5230.88,N,1318.92,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120745,A,5230.88,N,1318.92,E,15.6,286.0,030308,11.2,W,A*3c
+$GPGGA,120746,5230.88,N,1318.92,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120746,A,5230.88,N,1318.92,E,23.3,303.0,030308,11.2,W,A*33
+$GPGGA,120747,5230.88,N,1318.91,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120747,A,5230.88,N,1318.91,E,25.3,298.0,030308,11.2,W,A*34
+$GPGGA,120748,5230.89,N,1318.9,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,120748,A,5230.89,N,1318.9,E,29.2,298.0,030308,11.2,W,A*06
+$GPGGA,120749,5230.89,N,1318.89,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120749,A,5230.89,N,1318.89,E,29.2,298.0,030308,11.2,W,A*3f
+$GPGGA,120750,5230.89,N,1318.88,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120750,A,5230.89,N,1318.88,E,29.2,303.0,030308,11.2,W,A*35
+$GPGGA,120751,5230.9,N,1318.87,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,120751,A,5230.9,N,1318.87,E,29.2,300.0,030308,11.2,W,A*00
+$GPGGA,120752,5230.9,N,1318.86,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,120752,A,5230.9,N,1318.86,E,29.2,294.0,030308,11.2,W,A*0e
+$GPGGA,120753,5230.9,N,1318.85,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,120753,A,5230.9,N,1318.85,E,29.2,296.0,030308,11.2,W,A*0e
+$GPGGA,120754,5230.91,N,1318.84,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120754,A,5230.91,N,1318.84,E,25.3,294.0,030308,11.2,W,A*36
+$GPGGA,120755,5230.91,N,1318.83,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120755,A,5230.91,N,1318.83,E,25.8,298.0,030308,11.2,W,A*37
+$GPGGA,120756,5230.91,N,1318.82,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120756,A,5230.91,N,1318.82,E,26.2,293.0,030308,11.2,W,A*37
+$GPGGA,120757,5230.92,N,1318.8,E,1,07,1.3,50.6,M,39.2,M,,*76
+$GPRMC,120757,A,5230.92,N,1318.8,E,27.2,297.0,030308,11.2,W,A*02
+$GPGGA,120758,5230.92,N,1318.79,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120758,A,5230.92,N,1318.79,E,29.2,296.0,030308,11.2,W,A*34
+$GPGGA,120759,5230.93,N,1318.77,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120759,A,5230.93,N,1318.77,E,35.0,293.0,030308,11.2,W,A*30
+$GPGGA,120800,5230.93,N,1318.76,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120800,A,5230.93,N,1318.76,E,36.9,300.0,030308,11.2,W,A*33
+$GPGGA,120801,5230.94,N,1318.74,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120801,A,5230.94,N,1318.74,E,38.9,296.0,030308,11.2,W,A*37
+$GPGGA,120802,5230.94,N,1318.73,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120802,A,5230.94,N,1318.73,E,38.9,303.0,030308,11.2,W,A*3e
+$GPGGA,120803,5230.95,N,1318.71,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120803,A,5230.95,N,1318.71,E,38.9,299.0,030308,11.2,W,A*3e
+$GPGGA,120804,5230.95,N,1318.69,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120804,A,5230.95,N,1318.69,E,38.9,295.0,030308,11.2,W,A*3c
+$GPGGA,120805,5230.96,N,1318.67,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120805,A,5230.96,N,1318.67,E,38.9,298.0,030308,11.2,W,A*3d
+$GPGGA,120806,5230.96,N,1318.66,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120806,A,5230.96,N,1318.66,E,38.9,297.0,030308,11.2,W,A*30
+$GPGGA,120807,5230.97,N,1318.65,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120807,A,5230.97,N,1318.65,E,38.9,303.0,030308,11.2,W,A*3f
+$GPGGA,120808,5230.97,N,1318.64,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120808,A,5230.97,N,1318.64,E,38.9,298.0,030308,11.2,W,A*32
+$GPGGA,120809,5230.98,N,1318.62,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120809,A,5230.98,N,1318.62,E,26.2,300.0,030308,11.2,W,A*3e
+$GPGGA,120810,5230.98,N,1318.61,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120810,A,5230.98,N,1318.61,E,25.8,292.0,030308,11.2,W,A*36
+$GPGGA,120811,5230.98,N,1318.6,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120811,A,5230.98,N,1318.6,E,25.8,295.0,030308,11.2,W,A*01
+$GPGGA,120812,5230.99,N,1318.59,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120812,A,5230.99,N,1318.59,E,23.3,297.0,030308,11.2,W,A*36
+$GPGGA,120813,5230.99,N,1318.57,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120813,A,5230.99,N,1318.57,E,19.4,297.0,030308,11.2,W,A*37
+$GPGGA,120814,5230.99,N,1318.56,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120814,A,5230.99,N,1318.56,E,13.6,295.0,030308,11.2,W,A*3b
+$GPGGA,120815,5231,N,1318.55,E,1,07,1.3,50.6,M,39.2,M,,*63
+$GPRMC,120815,A,5231,N,1318.55,E,13.6,300.0,030308,11.2,W,A*1b
+$GPGGA,120816,5231,N,1318.54,E,1,07,1.3,50.6,M,39.2,M,,*61
+$GPRMC,120816,A,5231,N,1318.54,E,13.6,299.0,030308,11.2,W,A*18
+$GPGGA,120817,5231.01,N,1318.53,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120817,A,5231.01,N,1318.53,E,19.4,298.0,030308,11.2,W,A*38
+$GPGGA,120818,5231.01,N,1318.52,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120818,A,5231.01,N,1318.52,E,30.6,298.0,030308,11.2,W,A*3f
+$GPGGA,120819,5231.01,N,1318.5,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,120819,A,5231.01,N,1318.5,E,31.1,297.0,030308,11.2,W,A*05
+$GPGGA,120820,5231.02,N,1318.49,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120820,A,5231.02,N,1318.49,E,31.1,299.0,030308,11.2,W,A*3a
+$GPGGA,120821,5231.02,N,1318.48,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,120821,A,5231.02,N,1318.48,E,31.1,298.0,030308,11.2,W,A*3b
+$GPGGA,120822,5231.03,N,1318.47,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120822,A,5231.03,N,1318.47,E,30.6,299.0,030308,11.2,W,A*31
+$GPGGA,120823,5231.03,N,1318.45,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120823,A,5231.03,N,1318.45,E,30.1,302.0,030308,11.2,W,A*36
+$GPGGA,120824,5231.04,N,1318.44,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120824,A,5231.04,N,1318.44,E,30.1,299.0,030308,11.2,W,A*34
+$GPGGA,120825,5231.04,N,1318.43,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120825,A,5231.04,N,1318.43,E,35.0,298.0,030308,11.2,W,A*37
+$GPGGA,120826,5231.05,N,1318.41,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120826,A,5231.05,N,1318.41,E,35.0,298.0,030308,11.2,W,A*37
+$GPGGA,120827,5231.05,N,1318.4,E,1,07,1.3,50.6,M,39.2,M,,*7d
+$GPRMC,120827,A,5231.05,N,1318.4,E,27.7,297.0,030308,11.2,W,A*0c
+$GPGGA,120828,5231.05,N,1318.38,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120828,A,5231.05,N,1318.38,E,27.2,295.0,030308,11.2,W,A*3b
+$GPGGA,120829,5231.06,N,1318.37,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120829,A,5231.06,N,1318.37,E,27.2,291.0,030308,11.2,W,A*32
+$GPGGA,120830,5231.06,N,1318.36,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120830,A,5231.06,N,1318.36,E,25.3,302.0,030308,11.2,W,A*33
+$GPGGA,120831,5231.06,N,1318.35,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120831,A,5231.06,N,1318.35,E,23.3,301.0,030308,11.2,W,A*34
+$GPGGA,120832,5231.07,N,1318.34,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120832,A,5231.07,N,1318.34,E,19.4,295.0,030308,11.2,W,A*35
+$GPGGA,120833,5231.07,N,1318.33,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120833,A,5231.07,N,1318.33,E,15.6,297.0,030308,11.2,W,A*3f
+$GPGGA,120834,5231.07,N,1318.32,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120834,A,5231.07,N,1318.32,E,9.7,300.0,030308,11.2,W,A*0a
+$GPGGA,120835,5231.08,N,1318.32,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120835,A,5231.08,N,1318.32,E,5.8,300.0,030308,11.2,W,A*07
+$GPGGA,120836,5231.08,N,1318.31,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120836,A,5231.08,N,1318.31,E,3.9,298.0,030308,11.2,W,A*00
+$GPGGA,120837,5231.08,N,1318.31,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120837,A,5231.08,N,1318.31,E,1.9,289.0,030308,11.2,W,A*03
+$GPGGA,120838,5231.08,N,1318.3,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,120838,A,5231.08,N,1318.3,E,1.9,300.0,030308,11.2,W,A*3d
+$GPGGA,120839,5231.08,N,1318.3,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,120839,A,5231.08,N,1318.3,E,3.9,285.0,030308,11.2,W,A*32
+$GPGGA,120840,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120840,A,5231.08,N,1318.29,E,3.9,285.0,030308,11.2,W,A*04
+$GPGGA,120841,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120841,A,5231.08,N,1318.29,E,3.9,312.0,030308,11.2,W,A*0a
+$GPGGA,120842,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120842,A,5231.08,N,1318.29,E,1.9,285.0,030308,11.2,W,A*04
+$GPGGA,120843,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120843,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*13
+$GPGGA,120844,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120844,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*14
+$GPGGA,120845,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120845,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*15
+$GPGGA,120846,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120846,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*16
+$GPGGA,120847,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120847,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*17
+$GPGGA,120848,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120848,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*18
+$GPGGA,120849,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120849,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*19
+$GPGGA,120850,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120850,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*11
+$GPGGA,120851,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120851,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*10
+$GPGGA,120852,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120852,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*13
+$GPGGA,120853,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120853,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*12
+$GPGGA,120854,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120854,A,5231.08,N,1318.29,E,0,285.0,030308,11.2,W,A*15
+$GPGGA,120855,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120855,A,5231.08,N,1318.29,E,7.8,285.0,030308,11.2,W,A*05
+$GPGGA,120856,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120856,A,5231.08,N,1318.29,E,9.7,240.0,030308,11.2,W,A*0e
+$GPGGA,120857,5231.08,N,1318.28,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120857,A,5231.08,N,1318.28,E,11.7,281.0,030308,11.2,W,A*3a
+$GPGGA,120858,5231.09,N,1318.27,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120858,A,5231.09,N,1318.27,E,18.0,299.0,030308,11.2,W,A*3c
+$GPGGA,120859,5231.09,N,1318.26,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120859,A,5231.09,N,1318.26,E,19.9,297.0,030308,11.2,W,A*3a
+$GPGGA,120900,5231.09,N,1318.25,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120900,A,5231.09,N,1318.25,E,22.4,297.0,030308,11.2,W,A*31
+$GPGGA,120901,5231.1,N,1318.24,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,120901,A,5231.1,N,1318.24,E,22.8,303.0,030308,11.2,W,A*09
+$GPGGA,120902,5231.1,N,1318.23,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120902,A,5231.1,N,1318.23,E,21.9,293.0,030308,11.2,W,A*07
+$GPGGA,120903,5231.1,N,1318.22,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,120903,A,5231.1,N,1318.22,E,19.0,296.0,030308,11.2,W,A*00
+$GPGGA,120904,5231.1,N,1318.21,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,120904,A,5231.1,N,1318.21,E,15.1,300.0,030308,11.2,W,A*07
+$GPGGA,120905,5231.11,N,1318.2,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,120905,A,5231.11,N,1318.2,E,14.6,292.0,030308,11.2,W,A*0a
+$GPGGA,120906,5231.11,N,1318.19,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120906,A,5231.11,N,1318.19,E,16.0,297.0,030308,11.2,W,A*32
+$GPGGA,120907,5231.11,N,1318.18,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120907,A,5231.11,N,1318.18,E,19.0,293.0,030308,11.2,W,A*39
+$GPGGA,120908,5231.12,N,1318.17,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120908,A,5231.12,N,1318.17,E,21.4,297.0,030308,11.2,W,A*31
+$GPGGA,120909,5231.12,N,1318.16,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120909,A,5231.12,N,1318.16,E,24.3,296.0,030308,11.2,W,A*32
+$GPGGA,120910,5231.12,N,1318.15,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120910,A,5231.12,N,1318.15,E,25.8,301.0,030308,11.2,W,A*3c
+$GPGGA,120911,5231.13,N,1318.14,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120911,A,5231.13,N,1318.14,E,26.2,303.0,030308,11.2,W,A*36
+$GPGGA,120912,5231.13,N,1318.13,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120912,A,5231.13,N,1318.13,E,26.7,299.0,030308,11.2,W,A*35
+$GPGGA,120913,5231.14,N,1318.12,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120913,A,5231.14,N,1318.12,E,27.2,299.0,030308,11.2,W,A*36
+$GPGGA,120914,5231.14,N,1318.1,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,120914,A,5231.14,N,1318.1,E,28.2,297.0,030308,11.2,W,A*02
+$GPGGA,120915,5231.14,N,1318.09,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120915,A,5231.14,N,1318.09,E,29.2,304.0,030308,11.2,W,A*31
+$GPGGA,120916,5231.15,N,1318.08,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120916,A,5231.15,N,1318.08,E,29.6,302.0,030308,11.2,W,A*30
+$GPGGA,120917,5231.15,N,1318.07,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120917,A,5231.15,N,1318.07,E,30.6,305.0,030308,11.2,W,A*31
+$GPGGA,120918,5231.16,N,1318.06,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120918,A,5231.16,N,1318.06,E,31.6,305.0,030308,11.2,W,A*3d
+$GPGGA,120919,5231.16,N,1318.05,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,120919,A,5231.16,N,1318.05,E,31.6,300.0,030308,11.2,W,A*3a
+$GPGGA,120920,5231.17,N,1318.03,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120920,A,5231.17,N,1318.03,E,30.6,298.0,030308,11.2,W,A*36
+$GPGGA,120921,5231.17,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120921,A,5231.17,N,1318.02,E,28.2,296.0,030308,11.2,W,A*35
+$GPGGA,120922,5231.17,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120922,A,5231.17,N,1318.01,E,26.2,293.0,030308,11.2,W,A*3e
+$GPGGA,120923,5231.18,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*6e
+$GPRMC,120923,A,5231.18,N,1318,E,23.8,299.0,030308,11.2,W,A*1a
+$GPGGA,120924,5231.18,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120924,A,5231.18,N,1317.99,E,21.4,298.0,030308,11.2,W,A*33
+$GPGGA,120925,5231.19,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120925,A,5231.19,N,1317.98,E,20.4,306.0,030308,11.2,W,A*35
+$GPGGA,120926,5231.19,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120926,A,5231.19,N,1317.98,E,21.9,354.0,030308,11.2,W,A*3d
+$GPGGA,120927,5231.21,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120927,A,5231.21,N,1317.97,E,23.3,349.0,030308,11.2,W,A*3c
+$GPGGA,120928,5231.22,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120928,A,5231.22,N,1317.97,E,28.7,352.0,030308,11.2,W,A*35
+$GPGGA,120929,5231.23,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120929,A,5231.23,N,1317.97,E,29.6,355.0,030308,11.2,W,A*32
+$GPGGA,120930,5231.24,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120930,A,5231.24,N,1317.97,E,30.1,4.0,030308,11.2,W,A*35
+$GPGGA,120931,5231.25,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120931,A,5231.25,N,1317.97,E,29.6,7.0,030308,11.2,W,A*39
+$GPGGA,120932,5231.26,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120932,A,5231.26,N,1317.98,E,31.6,18.0,030308,11.2,W,A*01
+$GPGGA,120933,5231.27,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,120933,A,5231.27,N,1317.98,E,33.5,20.0,030308,11.2,W,A*0b
+$GPGGA,120934,5231.27,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,120934,A,5231.27,N,1317.99,E,33.5,22.0,030308,11.2,W,A*0f
+$GPGGA,120935,5231.28,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120935,A,5231.28,N,1317.99,E,32.6,19.0,030308,11.2,W,A*0b
+$GPGGA,120936,5231.29,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*68
+$GPRMC,120936,A,5231.29,N,1318,E,31.1,23.0,030308,11.2,W,A*25
+$GPGGA,120937,5231.3,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*51
+$GPRMC,120937,A,5231.3,N,1318,E,31.1,12.0,030308,11.2,W,A*1e
+$GPGGA,120938,5231.31,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120938,A,5231.31,N,1318.01,E,29.6,16.0,030308,11.2,W,A*05
+$GPGGA,120939,5231.32,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,120939,A,5231.32,N,1318.02,E,25.3,21.0,030308,11.2,W,A*09
+$GPGGA,120940,5231.33,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120940,A,5231.33,N,1318.02,E,23.3,16.0,030308,11.2,W,A*04
+$GPGGA,120941,5231.34,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120941,A,5231.34,N,1318.02,E,23.3,13.0,030308,11.2,W,A*07
+$GPGGA,120942,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120942,A,5231.35,N,1318.02,E,23.3,6.0,030308,11.2,W,A*31
+$GPGGA,120943,5231.36,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,120943,A,5231.36,N,1318.02,E,20.4,347.0,030308,11.2,W,A*31
+$GPGGA,120944,5231.36,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120944,A,5231.36,N,1318.01,E,24.3,322.0,030308,11.2,W,A*35
+$GPGGA,120945,5231.37,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120945,A,5231.37,N,1318.01,E,26.7,321.0,030308,11.2,W,A*30
+$GPGGA,120946,5231.38,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*6f
+$GPRMC,120946,A,5231.38,N,1318,E,28.7,320.0,030308,11.2,W,A*1c
+$GPGGA,120947,5231.38,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,120947,A,5231.38,N,1317.99,E,30.6,319.0,030308,11.2,W,A*3e
+$GPGGA,120948,5231.39,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,120948,A,5231.39,N,1317.98,E,32.1,323.0,030308,11.2,W,A*3d
+$GPGGA,120949,5231.4,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,120949,A,5231.4,N,1317.97,E,32.6,324.0,030308,11.2,W,A*0d
+$GPGGA,120950,5231.4,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,120950,A,5231.4,N,1317.96,E,32.6,325.0,030308,11.2,W,A*05
+$GPGGA,120951,5231.41,N,1317.95,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,120951,A,5231.41,N,1317.95,E,32.6,321.0,030308,11.2,W,A*32
+$GPGGA,120952,5231.42,N,1317.94,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,120952,A,5231.42,N,1317.94,E,33.0,326.0,030308,11.2,W,A*33
+$GPGGA,120953,5231.43,N,1317.93,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,120953,A,5231.43,N,1317.93,E,33.5,323.0,030308,11.2,W,A*34
+$GPGGA,120954,5231.44,N,1317.92,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,120954,A,5231.44,N,1317.92,E,32.6,323.0,030308,11.2,W,A*37
+$GPGGA,120955,5231.45,N,1317.91,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,120955,A,5231.45,N,1317.91,E,32.1,308.0,030308,11.2,W,A*3a
+$GPGGA,120956,5231.45,N,1317.9,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,120956,A,5231.45,N,1317.9,E,32.1,331.0,030308,11.2,W,A*02
+$GPGGA,120957,5231.46,N,1317.89,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,120957,A,5231.46,N,1317.89,E,31.1,327.0,030308,11.2,W,A*3c
+$GPGGA,120958,5231.47,N,1317.88,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,120958,A,5231.47,N,1317.88,E,31.1,317.0,030308,11.2,W,A*30
+$GPGGA,120959,5231.48,N,1317.88,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,120959,A,5231.48,N,1317.88,E,33.0,352.0,030308,11.2,W,A*3c
+$GPGGA,121000,5231.49,N,1317.88,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121000,A,5231.49,N,1317.88,E,33.0,352.0,030308,11.2,W,A*39
+$GPGGA,121001,5231.5,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,121001,A,5231.5,N,1317.87,E,33.0,341.0,030308,11.2,W,A*0d
+$GPGGA,121002,5231.51,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,121002,A,5231.51,N,1317.87,E,32.6,347.0,030308,11.2,W,A*3e
+$GPGGA,121003,5231.52,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121003,A,5231.52,N,1317.86,E,32.1,348.0,030308,11.2,W,A*35
+$GPGGA,121004,5231.53,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,121004,A,5231.53,N,1317.86,E,31.6,349.0,030308,11.2,W,A*36
+$GPGGA,121005,5231.54,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121005,A,5231.54,N,1317.86,E,30.6,350.0,030308,11.2,W,A*39
+$GPGGA,121006,5231.55,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121006,A,5231.55,N,1317.85,E,29.2,347.0,030308,11.2,W,A*32
+$GPGGA,121007,5231.56,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,121007,A,5231.56,N,1317.85,E,25.8,349.0,030308,11.2,W,A*38
+$GPGGA,121008,5231.57,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,121008,A,5231.57,N,1317.85,E,15.6,354.0,030308,11.2,W,A*37
+$GPGGA,121009,5231.58,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,121009,A,5231.58,N,1317.85,E,3.9,347.0,030308,11.2,W,A*03
+$GPGGA,121010,5231.58,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,121010,A,5231.58,N,1317.85,E,11.7,344.0,030308,11.2,W,A*35
+$GPGGA,121011,5231.58,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,121011,A,5231.58,N,1317.85,E,13.6,356.0,030308,11.2,W,A*34
+$GPGGA,121012,5231.58,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,121012,A,5231.58,N,1317.84,E,15.6,299.0,030308,11.2,W,A*32
+$GPGGA,121013,5231.58,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,121013,A,5231.58,N,1317.84,E,15.6,335.0,030308,11.2,W,A*34
+$GPGGA,121014,5231.59,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,121014,A,5231.59,N,1317.84,E,19.4,350.0,030308,11.2,W,A*3f
+$GPGGA,121015,5231.59,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121015,A,5231.59,N,1317.84,E,19.4,353.0,030308,11.2,W,A*3d
+$GPGGA,121016,5231.61,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,121016,A,5231.61,N,1317.84,E,25.3,347.0,030308,11.2,W,A*38
+$GPGGA,121017,5231.61,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121017,A,5231.61,N,1317.83,E,25.3,349.0,030308,11.2,W,A*30
+$GPGGA,121018,5231.62,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,121018,A,5231.62,N,1317.83,E,26.7,351.0,030308,11.2,W,A*32
+$GPGGA,121019,5231.63,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,121019,A,5231.63,N,1317.83,E,29.2,354.0,030308,11.2,W,A*3d
+$GPGGA,121020,5231.64,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121020,A,5231.64,N,1317.83,E,30.1,349.0,030308,11.2,W,A*37
+$GPGGA,121021,5231.65,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121021,A,5231.65,N,1317.83,E,31.1,350.0,030308,11.2,W,A*3e
+$GPGGA,121022,5231.65,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,121022,A,5231.65,N,1317.82,E,32.6,349.0,030308,11.2,W,A*30
+$GPGGA,121023,5231.66,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121023,A,5231.66,N,1317.82,E,33.0,350.0,030308,11.2,W,A*3d
+$GPGGA,121024,5231.67,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121024,A,5231.67,N,1317.82,E,33.0,350.0,030308,11.2,W,A*3b
+$GPGGA,121025,5231.68,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,121025,A,5231.68,N,1317.82,E,33.5,346.0,030308,11.2,W,A*37
+$GPGGA,121026,5231.69,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,121026,A,5231.69,N,1317.81,E,33.5,353.0,030308,11.2,W,A*32
+$GPGGA,121027,5231.7,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,121027,A,5231.7,N,1317.81,E,33.0,354.0,030308,11.2,W,A*09
+$GPGGA,121028,5231.71,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,121028,A,5231.71,N,1317.81,E,33.0,349.0,030308,11.2,W,A*3b
+$GPGGA,121029,5231.72,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,121029,A,5231.72,N,1317.81,E,31.1,348.0,030308,11.2,W,A*3b
+$GPGGA,121030,5231.72,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,121030,A,5231.72,N,1317.8,E,30.1,343.0,030308,11.2,W,A*08
+$GPGGA,121031,5231.73,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,121031,A,5231.73,N,1317.8,E,28.2,345.0,030308,11.2,W,A*04
+$GPGGA,121032,5231.74,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,121032,A,5231.74,N,1317.8,E,24.8,341.0,030308,11.2,W,A*02
+$GPGGA,121033,5231.74,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121033,A,5231.74,N,1317.79,E,20.4,348.0,030308,11.2,W,A*34
+$GPGGA,121034,5231.75,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121034,A,5231.75,N,1317.79,E,16.0,347.0,030308,11.2,W,A*3c
+$GPGGA,121035,5231.75,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121035,A,5231.75,N,1317.79,E,14.6,354.0,030308,11.2,W,A*3b
+$GPGGA,121036,5231.75,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,121036,A,5231.75,N,1317.79,E,3.9,336.0,030308,11.2,W,A*05
+$GPGGA,121037,5231.75,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,121037,A,5231.75,N,1317.79,E,2.9,290.0,030308,11.2,W,A*08
+$GPGGA,121038,5231.76,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121038,A,5231.76,N,1317.79,E,2.9,343.0,030308,11.2,W,A*0b
+$GPGGA,121039,5231.76,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,121039,A,5231.76,N,1317.79,E,13.6,344.0,030308,11.2,W,A*32
+$GPGGA,121040,5231.76,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121040,A,5231.76,N,1317.78,E,17.5,339.0,030308,11.2,W,A*30
+$GPGGA,121041,5231.77,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121041,A,5231.77,N,1317.78,E,19.9,352.0,030308,11.2,W,A*3f
+$GPGGA,121042,5231.78,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,121042,A,5231.78,N,1317.78,E,21.9,344.0,030308,11.2,W,A*3f
+$GPGGA,121043,5231.79,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,121043,A,5231.79,N,1317.77,E,23.3,343.0,030308,11.2,W,A*3f
+$GPGGA,121044,5231.8,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,121044,A,5231.8,N,1317.77,E,23.3,356.0,030308,11.2,W,A*0a
+$GPGGA,121045,5231.81,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,121045,A,5231.81,N,1317.77,E,17.5,342.0,030308,11.2,W,A*3e
+$GPGGA,121046,5231.81,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121046,A,5231.81,N,1317.77,E,11.2,352.0,030308,11.2,W,A*3d
+$GPGGA,121047,5231.81,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121047,A,5231.81,N,1317.77,E,1.9,340.0,030308,11.2,W,A*05
+$GPGGA,121048,5231.81,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,121048,A,5231.81,N,1317.77,E,1.9,343.0,030308,11.2,W,A*09
+$GPGGA,121049,5231.81,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,121049,A,5231.81,N,1317.76,E,1.5,324.0,030308,11.2,W,A*04
+$GPGGA,121050,5231.81,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121050,A,5231.81,N,1317.76,E,2.4,313.0,030308,11.2,W,A*0a
+$GPGGA,121051,5231.81,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,121051,A,5231.81,N,1317.76,E,11.7,347.0,030308,11.2,W,A*3b
+$GPGGA,121052,5231.82,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,121052,A,5231.82,N,1317.76,E,17.5,345.0,030308,11.2,W,A*3d
+$GPGGA,121053,5231.82,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121053,A,5231.82,N,1317.76,E,19.4,345.0,030308,11.2,W,A*33
+$GPGGA,121054,5231.83,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121054,A,5231.83,N,1317.76,E,19.4,350.0,030308,11.2,W,A*31
+$GPGGA,121055,5231.83,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121055,A,5231.83,N,1317.76,E,21.9,348.0,030308,11.2,W,A*3f
+$GPGGA,121056,5231.84,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121056,A,5231.84,N,1317.75,E,24.3,344.0,030308,11.2,W,A*3b
+$GPGGA,121057,5231.85,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121057,A,5231.85,N,1317.75,E,25.3,342.0,030308,11.2,W,A*3c
+$GPGGA,121058,5231.86,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,121058,A,5231.86,N,1317.75,E,27.7,351.0,030308,11.2,W,A*34
+$GPGGA,121059,5231.86,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,121059,A,5231.86,N,1317.74,E,28.7,346.0,030308,11.2,W,A*3d
+$GPGGA,121100,5231.87,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,121100,A,5231.87,N,1317.74,E,30.6,347.0,030308,11.2,W,A*38
+$GPGGA,121101,5231.88,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,121101,A,5231.88,N,1317.74,E,31.6,340.0,030308,11.2,W,A*30
+$GPGGA,121102,5231.89,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,121102,A,5231.89,N,1317.73,E,32.6,341.0,030308,11.2,W,A*37
+$GPGGA,121103,5231.9,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,121103,A,5231.9,N,1317.73,E,34.0,340.0,030308,11.2,W,A*0f
+$GPGGA,121104,5231.91,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,121104,A,5231.91,N,1317.72,E,35.0,341.0,030308,11.2,W,A*38
+$GPGGA,121105,5231.92,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,121105,A,5231.92,N,1317.72,E,35.5,342.0,030308,11.2,W,A*3c
+$GPGGA,121106,5231.93,N,1317.71,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121106,A,5231.93,N,1317.71,E,35.0,338.0,030308,11.2,W,A*35
+$GPGGA,121107,5231.94,N,1317.7,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,121107,A,5231.94,N,1317.7,E,34.0,336.0,030308,11.2,W,A*0d
+$GPGGA,121108,5231.94,N,1317.7,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,121108,A,5231.94,N,1317.7,E,32.6,337.0,030308,11.2,W,A*03
+$GPGGA,121109,5231.95,N,1317.69,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,121109,A,5231.95,N,1317.69,E,29.6,339.0,030308,11.2,W,A*3f
+$GPGGA,121110,5231.96,N,1317.69,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,121110,A,5231.96,N,1317.69,E,29.2,339.0,030308,11.2,W,A*30
+$GPGGA,121111,5231.97,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,121111,A,5231.97,N,1317.68,E,25.8,333.0,030308,11.2,W,A*3d
+$GPGGA,121112,5231.97,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,121112,A,5231.97,N,1317.68,E,25.3,339.0,030308,11.2,W,A*3f
+$GPGGA,121113,5231.98,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,121113,A,5231.98,N,1317.68,E,20.9,343.0,030308,11.2,W,A*33
+$GPGGA,121114,5231.98,N,1317.67,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121114,A,5231.98,N,1317.67,E,19.4,339.0,030308,11.2,W,A*31
+$GPGGA,121115,5231.99,N,1317.67,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121115,A,5231.99,N,1317.67,E,17.5,341.0,030308,11.2,W,A*31
+$GPGGA,121116,5231.99,N,1317.67,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,121116,A,5231.99,N,1317.67,E,16.5,344.0,030308,11.2,W,A*36
+$GPGGA,121117,5232,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*65
+$GPRMC,121117,A,5232,N,1317.66,E,14.6,324.0,030308,11.2,W,A*1c
+$GPGGA,121118,5232,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*6a
+$GPRMC,121118,A,5232,N,1317.66,E,12.6,332.0,030308,11.2,W,A*12
+$GPGGA,121119,5232,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*6b
+$GPRMC,121119,A,5232,N,1317.66,E,14.1,342.0,030308,11.2,W,A*15
+$GPGGA,121120,5232.01,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,121120,A,5232.01,N,1317.66,E,16.5,339.0,030308,11.2,W,A*3a
+$GPGGA,121121,5232.01,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,121121,A,5232.01,N,1317.65,E,16.5,335.0,030308,11.2,W,A*34
+$GPGGA,121122,5232.01,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,121122,A,5232.01,N,1317.65,E,16.5,322.0,030308,11.2,W,A*31
+$GPGGA,121123,5232.02,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,121123,A,5232.02,N,1317.65,E,16.5,334.0,030308,11.2,W,A*34
+$GPGGA,121124,5232.02,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121124,A,5232.02,N,1317.64,E,19.0,331.0,030308,11.2,W,A*3d
+$GPGGA,121125,5232.03,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121125,A,5232.03,N,1317.64,E,17.0,338.0,030308,11.2,W,A*3a
+$GPGGA,121126,5232.03,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,121126,A,5232.03,N,1317.64,E,13.6,334.0,030308,11.2,W,A*37
+$GPGGA,121127,5232.03,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,121127,A,5232.03,N,1317.64,E,11.2,349.0,030308,11.2,W,A*3a
+$GPGGA,121128,5232.03,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,121128,A,5232.03,N,1317.64,E,1.9,352.0,030308,11.2,W,A*05
+$GPGGA,121129,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,121129,A,5232.04,N,1317.64,E,1.9,352.0,030308,11.2,W,A*03
+$GPGGA,121130,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,121130,A,5232.04,N,1317.64,E,0.5,352.0,030308,11.2,W,A*06
+$GPGGA,121131,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,121131,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*1c
+$GPGGA,121132,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,121132,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*1f
+$GPGGA,121133,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121133,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*1e
+$GPGGA,121134,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,121134,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*19
+$GPGGA,121135,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,121135,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*18
+$GPGGA,121136,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,121136,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*1b
+$GPGGA,121137,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,121137,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*1a
+$GPGGA,121138,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,121138,A,5232.04,N,1317.64,E,0,352.0,030308,11.2,W,A*15
+$GPGGA,121139,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,121139,A,5232.04,N,1317.64,E,1.0,352.0,030308,11.2,W,A*0b
+$GPGGA,121140,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,121140,A,5232.04,N,1317.64,E,7.8,357.0,030308,11.2,W,A*0e
+$GPGGA,121141,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,121141,A,5232.04,N,1317.64,E,15.6,357.0,030308,11.2,W,A*32
+$GPGGA,121142,5232.05,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,121142,A,5232.05,N,1317.64,E,16.5,14.0,030308,11.2,W,A*04
+$GPGGA,121143,5232.05,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,121143,A,5232.05,N,1317.64,E,18.5,17.0,030308,11.2,W,A*08
+$GPGGA,121144,5232.06,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,121144,A,5232.06,N,1317.65,E,20.9,21.0,030308,11.2,W,A*0f
+$GPGGA,121145,5232.06,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,121145,A,5232.06,N,1317.65,E,20.9,18.0,030308,11.2,W,A*04
+$GPGGA,121146,5232.07,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121146,A,5232.07,N,1317.65,E,19.4,18.0,030308,11.2,W,A*01
+$GPGGA,121147,5232.07,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,121147,A,5232.07,N,1317.65,E,17.5,348.0,030308,11.2,W,A*39
+$GPGGA,121148,5232.08,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,121148,A,5232.08,N,1317.64,E,11.7,333.0,030308,11.2,W,A*30
+$GPGGA,121149,5232.08,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,121149,A,5232.08,N,1317.63,E,7.8,315.0,030308,11.2,W,A*0a
diff --git a/CanController/tcpclusterdatacontrol.cpp b/CanController/tcpclusterdatacontrol.cpp
new file mode 100644
index 0000000..a9aadca
--- /dev/null
+++ b/CanController/tcpclusterdatacontrol.cpp
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tcpclusterdatacontrol.h"
+#include <QHostAddress>
+#include <QDebug>
+#include <QTimer>
+
+TCPClusterDataControl::TCPClusterDataControl(QObject *parent)
+ : ClusterDataControlInterface(parent),
+ m_frontLeftDoorOpen(false),
+ m_frontRightDoorOpen(false),
+ m_rearLeftDoorOpen(false),
+ m_rearRightDoorOpen(false),
+ m_hoodOpen(false),
+ m_trunkOpen(false),
+ m_headLight(false),
+ m_parkLight(false),
+ m_rightTurnLight(false),
+ m_leftTurnLight(false),
+ m_hazardSignal(false),
+ m_brake(false)
+{
+ connect(&m_tcpSocket, &QAbstractSocket::stateChanged,
+ this, &TCPClusterDataControl::onConnectionStateChanged);
+ connect(&m_tcpSocket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)> (&QAbstractSocket::error),
+ this, &TCPClusterDataControl::handleTcpError);
+
+ connectToServer();
+}
+
+TCPClusterDataControl::~TCPClusterDataControl()
+{
+ m_tcpSocket.close();
+}
+
+static bool printIP = true;
+
+void TCPClusterDataControl::connectToServer()
+{
+ QByteArray simu = qgetenv("QT_CLUSTER_SIMU");
+ QHostAddress simuAddr("127.0.0.1");
+
+ if (!simu.isEmpty()) {
+ if (!simuAddr.setAddress(QString(simu))) {
+ qWarning("Failed to set simulator address! Falling back to localhost");
+ simuAddr.setAddress("127.0.0.1");
+ }
+ }
+
+ if (printIP) {
+ printIP = false;
+ qDebug() << "Connecting to" << simuAddr;
+ }
+
+ m_tcpSocket.connectToHost(simuAddr,32123);
+}
+
+void TCPClusterDataControl::onConnectionStateChanged(QAbstractSocket::SocketState socketState)
+{
+ if (socketState == QAbstractSocket::UnconnectedState) {
+ QTimer::singleShot(1000,Qt::VeryCoarseTimer, this, SLOT(connectToServer()));
+ } else if (socketState == QAbstractSocket::ConnectedState) {
+ qDebug() << "Connected";
+ emit dataReset();
+ }
+}
+
+void TCPClusterDataControl::handleTcpError(QAbstractSocket::SocketError socketError)
+{
+ Q_UNUSED(socketError);
+ qWarning() << "TCP Error:" << m_tcpSocket.errorString();
+}
+
+int TCPClusterDataControl::carId() const
+{
+ return m_carId;
+}
+
+bool TCPClusterDataControl::headLight() const
+{
+ return m_headLight;
+}
+
+bool TCPClusterDataControl::parkLight() const
+{
+ return m_parkLight;
+}
+
+bool TCPClusterDataControl::rightTurnLight() const
+{
+ return m_rightTurnLight;
+}
+
+bool TCPClusterDataControl::leftTurnLight() const
+{
+ return m_leftTurnLight;
+}
+
+int TCPClusterDataControl::gear() const
+{
+ return m_gear;
+}
+
+bool TCPClusterDataControl::lightFailure() const
+{
+ return m_lightFailure;
+}
+
+bool TCPClusterDataControl::frontLeftDoorOpen() const
+{
+ return m_frontLeftDoorOpen;
+}
+
+bool TCPClusterDataControl::frontRightDoorOpen() const
+{
+ return m_frontRightDoorOpen;
+}
+
+bool TCPClusterDataControl::rearLeftDoorOpen() const
+{
+ return m_rearLeftDoorOpen;
+}
+
+bool TCPClusterDataControl::rearRightDoorOpen() const
+{
+ return m_rearRightDoorOpen;
+}
+
+bool TCPClusterDataControl::hoodOpen() const
+{
+ return m_hoodOpen;
+}
+
+bool TCPClusterDataControl::trunkOpen() const
+{
+ return m_trunkOpen;
+}
+
+bool TCPClusterDataControl::flatTire() const
+{
+ return m_flatTire;
+}
+
+double TCPClusterDataControl::direction() const
+{
+ return m_direction;
+}
+
+double TCPClusterDataControl::longitude() const
+{
+ return m_longitude;
+}
+
+double TCPClusterDataControl::latitude() const
+{
+ return m_latitude;
+}
+
+double TCPClusterDataControl::vehicleSpeed() const
+{
+ return m_vehicleSpeed;
+}
+
+bool TCPClusterDataControl::hazardSignal() const
+{
+ return m_hazardSignal;
+}
+
+bool TCPClusterDataControl::brake() const
+{
+ return m_brake;
+}
+
+double TCPClusterDataControl::oilTemp() const
+{
+ return m_oilTemp;
+}
+
+int TCPClusterDataControl::oilPressure() const
+{
+ return m_oilPressure;
+}
+
+double TCPClusterDataControl::batteryPotential() const
+{
+ return m_batteryPotential;
+}
+
+double TCPClusterDataControl::gasLevel() const
+{
+ return m_gasLevel;
+}
+
+int TCPClusterDataControl::rpm() const
+{
+ return m_rpm;
+}
+
+int TCPClusterDataControl::engineTemp() const
+{
+ return m_engineTemp;
+}
+
+void TCPClusterDataControl::setVehicleSpeed(double vehicleSpeed)
+{
+ if (m_vehicleSpeed == vehicleSpeed)
+ return;
+
+ QString msg("vehicleSpeed:" + QString::number(vehicleSpeed) + " ");
+ write(msg.toLatin1());
+
+ m_vehicleSpeed = vehicleSpeed;
+ emit vehicleSpeedChanged(vehicleSpeed);
+}
+
+void TCPClusterDataControl::setLatitude(double latitude)
+{
+ if (m_latitude == latitude)
+ return;
+
+ QString msg("latitude:" + QString::number(latitude) + " ");
+ write(msg.toLatin1(), msg.length());
+
+ m_latitude = latitude;
+ emit latitudeChanged(latitude);
+}
+
+void TCPClusterDataControl::setLongitude(double longitude)
+{
+ if (m_longitude == longitude)
+ return;
+
+ QString msg("longitude:" + QString::number(longitude) + " ");
+ write(msg.toLatin1());
+
+ m_longitude = longitude;
+ emit longitudeChanged(longitude);
+}
+
+void TCPClusterDataControl::setDirection(double direction)
+{
+ if (m_direction == direction)
+ return;
+
+ QString msg("direction:" + QString::number(direction) + " ");
+ write(msg.toLatin1());
+
+ m_direction = direction;
+ emit directionChanged(direction);
+}
+
+void TCPClusterDataControl::setFlatTire(bool flatTire)
+{
+ if (m_flatTire == flatTire)
+ return;
+
+ QString msg("flatTire:" + QString::number(flatTire) + " ");
+ write(msg.toLatin1());
+
+ m_flatTire = flatTire;
+ emit flatTireChanged(flatTire);
+}
+
+void TCPClusterDataControl::setFrontLeftDoorOpen(bool doorOpen)
+{
+ if (m_frontLeftDoorOpen == doorOpen)
+ return;
+
+ QString msg("frontLeftDoorOpen:" + QString::number(doorOpen) + " ");
+ write(msg.toLatin1());
+
+ m_frontLeftDoorOpen = doorOpen;
+ emit frontLeftDoorOpenChanged(doorOpen);
+}
+
+void TCPClusterDataControl::setFrontRightDoorOpen(bool doorOpen)
+{
+ if (m_frontRightDoorOpen == doorOpen)
+ return;
+
+ QString msg("frontRightDoorOpen:" + QString::number(doorOpen) + " ");
+ write(msg.toLatin1());
+
+ m_frontRightDoorOpen = doorOpen;
+ emit frontRightDoorOpenChanged(doorOpen);
+}
+
+void TCPClusterDataControl::setRearLeftDoorOpen(bool doorOpen)
+{
+ if (m_rearLeftDoorOpen == doorOpen)
+ return;
+
+ QString msg("rearLeftDoorOpen:" + QString::number(doorOpen) + " ");
+ write(msg.toLatin1());
+
+ m_rearLeftDoorOpen = doorOpen;
+ emit rearLeftDoorOpenChanged(doorOpen);
+}
+
+void TCPClusterDataControl::setHoodOpen(bool doorOpen)
+{
+ if (m_hoodOpen == doorOpen)
+ return;
+
+ QString msg("hoodOpen:" + QString::number(doorOpen) + " ");
+ write(msg.toLatin1());
+
+ m_hoodOpen = doorOpen;
+ emit hoodOpenChanged(doorOpen);
+}
+
+void TCPClusterDataControl::setTrunkOpen(bool doorOpen)
+{
+ if (m_trunkOpen == doorOpen)
+ return;
+
+ QString msg("trunkOpen:" + QString::number(doorOpen) + " ");
+ write(msg.toLatin1());
+
+ m_trunkOpen = doorOpen;
+ emit rearRightDoorOpenChanged(doorOpen);
+}
+
+void TCPClusterDataControl::setRearRightDoorOpen(bool doorOpen)
+{
+ if (m_rearRightDoorOpen == doorOpen)
+ return;
+
+ QString msg("rearRightDoorOpen:" + QString::number(doorOpen) + " ");
+ write(msg.toLatin1());
+
+ m_rearRightDoorOpen = doorOpen;
+ emit rearRightDoorOpenChanged(doorOpen);
+}
+
+void TCPClusterDataControl::setLightFailure(bool lightFailure)
+{
+ if (m_lightFailure == lightFailure)
+ return;
+
+ QString msg("lightFailure:" + QString::number(lightFailure) + " ");
+ write(msg.toLatin1());
+
+ m_lightFailure = lightFailure;
+ emit lightFailureChanged(lightFailure);
+}
+
+void TCPClusterDataControl::setGear(int gear)
+{
+ if (m_gear == gear)
+ return;
+
+ QString msg("gear:" + QString::number(gear) + " ");
+ write(msg.toLatin1());
+
+ m_gear = gear;
+ emit gearChanged(gear);
+}
+
+void TCPClusterDataControl::setLeftTurnLight(bool leftTurnLight)
+{
+ if (m_leftTurnLight == leftTurnLight)
+ return;
+
+ QString msg("leftTurnLight:" + QString::number(leftTurnLight) + " ");
+ write(msg.toLatin1());
+
+ m_leftTurnLight = leftTurnLight;
+ emit leftTurnLightChanged(leftTurnLight);
+}
+
+void TCPClusterDataControl::setRightTurnLight(bool rightTurnLight)
+{
+ if (m_rightTurnLight == rightTurnLight)
+ return;
+
+ QString msg("rightTurnLight:" + QString::number(rightTurnLight) + " ");
+ write(msg.toLatin1());
+
+ m_rightTurnLight = rightTurnLight;
+ emit rightTurnLightChanged(rightTurnLight);
+}
+
+void TCPClusterDataControl::setHeadLight(bool headLight)
+{
+ if (m_headLight == headLight)
+ return;
+
+ QString msg("headLight:" + QString::number(headLight) + " ");
+ write(msg.toLatin1());
+
+ m_headLight = headLight;
+ emit headLightChanged(headLight);
+}
+
+void TCPClusterDataControl::setParkLight(bool parkLight)
+{
+ if (m_parkLight == parkLight)
+ return;
+
+ QString msg("parkLight:" + QString::number(parkLight) + " ");
+ write(msg.toLatin1());
+
+ m_parkLight = parkLight;
+ emit parkLightChanged(parkLight);
+}
+
+void TCPClusterDataControl::setCarId(int carId)
+{
+ if (m_carId == carId)
+ return;
+
+ QString msg("carId:" + QString::number(carId) + " ");
+ write(msg.toLatin1());
+
+ m_carId = carId;
+ emit carIdChanged(carId);
+}
+
+void TCPClusterDataControl::setHazardSignal(bool hazardSignal)
+{
+ if (m_hazardSignal == hazardSignal)
+ return;
+
+ QString msg("hazardSignal:" + QString::number(hazardSignal) + " ");
+ write(msg.toLatin1());
+
+ m_hazardSignal = hazardSignal;
+ emit hazardSignalChanged(hazardSignal);
+}
+
+void TCPClusterDataControl::setBrake(bool brake)
+{
+ if (m_brake == brake)
+ return;
+
+ QString msg("brake:" + QString::number(brake) + " ");
+ write(msg.toLatin1());
+
+ m_brake = brake;
+ emit brakeChanged(brake);
+}
+
+void TCPClusterDataControl::setOilTemp(double oilTemp)
+{
+ if (m_oilTemp == oilTemp)
+ return;
+
+ QString msg("oilTemp:" + QString::number(oilTemp) + " ");
+ write(msg.toLatin1());
+
+ m_oilTemp = oilTemp;
+ emit oilTempChanged(oilTemp);
+}
+
+void TCPClusterDataControl::setOilPressure(int oilPressure)
+{
+ if (m_oilPressure == oilPressure)
+ return;
+
+ QString msg("oilPressure:" + QString::number(oilPressure) + " ");
+ write(msg.toLatin1());
+
+ m_oilPressure = oilPressure;
+ emit oilPressureChanged(oilPressure);
+}
+
+void TCPClusterDataControl::setBatteryPotential(double batteryPotential)
+{
+ if (m_batteryPotential == batteryPotential)
+ return;
+
+ QString msg("batteryPotential:" + QString::number(batteryPotential) + " ");
+ write(msg.toLatin1());
+
+ m_batteryPotential = batteryPotential;
+ emit batteryPotentialChanged(batteryPotential);
+}
+
+void TCPClusterDataControl::setGasLevel(double gasLevel)
+{
+ if (m_gasLevel == gasLevel)
+ return;
+
+ QString msg("gasLevel:" + QString::number(gasLevel) + " ");
+ write(msg.toLatin1());
+
+ m_gasLevel = gasLevel;
+ emit gasLevelChanged(gasLevel);
+}
+
+void TCPClusterDataControl::setRpm(int rpm)
+{
+ if (m_rpm == rpm)
+ return;
+
+ QString msg("rpm:" + QString::number(rpm) + " ");
+ write(msg.toLatin1());
+
+ m_rpm = rpm;
+ emit rpmChanged(rpm);
+}
+
+void TCPClusterDataControl::setEngineTemp(int engineTemp)
+{
+ if (m_engineTemp == engineTemp)
+ return;
+
+ QString msg("engineTemp:" + QString::number(engineTemp) + " ");
+ write(msg.toLatin1());
+
+ m_engineTemp = engineTemp;
+ emit engineTempChanged(engineTemp);
+}
+
+void TCPClusterDataControl::write(const char *data, qint64 length)
+{
+ if ((m_tcpSocket.state() == QTcpSocket::ConnectedState)) {
+ m_tcpSocket.write(data, length);
+ }
+}
+
+void TCPClusterDataControl::write(const char *data)
+{
+ if ((m_tcpSocket.state() == QTcpSocket::ConnectedState)) {
+ m_tcpSocket.write(data);
+ }
+}
diff --git a/CanController/tcpclusterdatacontrol.h b/CanController/tcpclusterdatacontrol.h
new file mode 100644
index 0000000..c3e2422
--- /dev/null
+++ b/CanController/tcpclusterdatacontrol.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TCPCLUSTERDATACONTROL_H
+#define TCPCLUSTERDATACONTROL_H
+
+#include "clusterdatacontrolinterface.h"
+
+#include <QTcpSocket>
+
+class TCPClusterDataControl : public ClusterDataControlInterface
+{
+ Q_OBJECT
+
+public:
+ TCPClusterDataControl(QObject *parent = 0);
+ ~TCPClusterDataControl();
+
+ int carId() const;
+ bool headLight() const;
+ bool parkLight() const;
+ bool rightTurnLight() const;
+ bool leftTurnLight() const;
+ int gear() const;
+ bool lightFailure() const;
+ bool frontLeftDoorOpen() const;
+ bool frontRightDoorOpen() const;
+ bool rearLeftDoorOpen() const;
+ bool rearRightDoorOpen() const;
+ bool hoodOpen() const;
+ bool trunkOpen() const;
+ bool flatTire() const;
+ double direction() const;
+ double longitude() const;
+ double latitude() const;
+ double vehicleSpeed() const;
+ bool hazardSignal() const;
+ bool brake() const;
+ double oilTemp() const;
+ int oilPressure() const;
+ double batteryPotential() const;
+ double gasLevel() const;
+ int rpm() const;
+ int engineTemp() const;
+
+public slots:
+ void connectToServer();
+ void onConnectionStateChanged(QAbstractSocket::SocketState socketState);
+ void handleTcpError(QAbstractSocket::SocketError socketError);
+
+ void setVehicleSpeed(double vehicleSpeed);
+ void setLatitude(double latitude);
+ void setLongitude(double longitude);
+ void setDirection(double direction);
+ void setFlatTire(bool flatTire);
+ void setFrontLeftDoorOpen(bool doorOpen);
+ void setFrontRightDoorOpen(bool doorOpen);
+ void setRearLeftDoorOpen(bool doorOpen);
+ void setRearRightDoorOpen(bool doorOpen);
+ void setHoodOpen(bool doorOpen);
+ void setTrunkOpen(bool doorOpen);
+ void setLightFailure(bool lightFailure);
+ void setGear(int gear);
+ void setLeftTurnLight(bool leftTurnLight);
+ void setRightTurnLight(bool rightTurnLight);
+ void setHeadLight(bool headLight);
+ void setParkLight(bool parkLight);
+ void setCarId(int carId);
+ void setHazardSignal(bool hazardSignal);
+ void setBrake(bool brake);
+ void setOilTemp(double oilTemp);
+ void setOilPressure(int oilPressure);
+ void setBatteryPotential(double batteryPotential);
+ void setGasLevel(double gasLevel);
+ void setRpm(int rpm);
+ void setEngineTemp(int engineTemp);
+
+private:
+ void write(const char *, qint64 );
+ void write(const char *);
+
+private:
+ QTcpSocket m_tcpSocket;
+ bool m_frontLeftDoorOpen;
+ bool m_frontRightDoorOpen;
+ bool m_rearLeftDoorOpen;
+ bool m_rearRightDoorOpen;
+ bool m_hoodOpen;
+ bool m_trunkOpen;
+ bool m_headLight;
+ bool m_parkLight;
+ bool m_rightTurnLight;
+ bool m_leftTurnLight;
+ bool m_hazardSignal;
+ bool m_brake;
+};
+
+#endif // TCPCLUSTERDATACONTROL_H
diff --git a/CanController/valuetypes.h b/CanController/valuetypes.h
new file mode 100644
index 0000000..ccea580
--- /dev/null
+++ b/CanController/valuetypes.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VALUETYPES
+#define VALUETYPES
+
+namespace NMEAType
+{
+ enum {
+ NMEAStart = 0x01,
+ NMEAEnd = 0x0f,
+
+ GeoBaseStart = 0x10,
+ GeoBaseEnd = 0x1f,
+
+ GGAStart = 0x20,
+ GGAEnd = 0x2f,
+
+ RMCStart = 0x30,
+ RMCEnd = 0x3f,
+ };
+
+ enum Type {
+ UndefinedType = 0,
+ GGAType,
+ RMCType
+ };
+
+ enum Value {
+ UTCTime = NMEAStart,
+ CheckSum,
+
+ Latitude = GeoBaseStart,
+ Longitude,
+
+ GGAQuality = GGAStart,
+ GGASatellites,
+ GGADilution,
+ GGAAltitude,
+ GGAGeoid,
+
+ RMCActive = RMCStart,
+ RMCSpeed,
+ RMCAngle,
+ RMCDate,
+ RMCVariation
+
+ };
+}
+
+#endif // VALUETYPES
+
diff --git a/CenterConsole/CenterConsole.pro b/CenterConsole/CenterConsole.pro
new file mode 100644
index 0000000..a10af1a
--- /dev/null
+++ b/CenterConsole/CenterConsole.pro
@@ -0,0 +1,10 @@
+include (../deployment.pri)
+TEMPLATE = subdirs
+
+SUBDIRS = plugins
+
+qml.files = apps sysui
+qml.path = $$TARGET_PATH_CONSOLE
+
+INSTALLS += qml
+
diff --git a/CenterConsole/apps/com.pelagicore.media/AlbumScreen.qml b/CenterConsole/apps/com.pelagicore.media/AlbumScreen.qml
new file mode 100644
index 0000000..27cf65a
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/AlbumScreen.qml
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+
+import service.music 1.0
+import service.movie 1.0
+import controls 1.0
+import utils 1.0
+import "."
+
+UIScreen {
+ id: root
+ property string modelType: "Music"
+
+ width: Style.screenWidth
+ title: modelType === "Music" ? 'Music' : 'Movies'
+ signal showCurrentTrack()
+
+ GridView {
+ id: grid
+ width: Style.screenWidth - 60
+ height: 1020
+ cellWidth: 340
+ cellHeight: root.modelType === "Music" ? 340 : 490
+ anchors.top: parent.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.margins: Style.statusBarHeight*2
+ model: modelType === "Music" ? MusicProvider.nowPlaying.model : MovieProvider.model
+ clip: true
+ snapMode: GridView.SnapToRow
+ delegate: Item {
+ width: 330
+ height: root.modelType === "Music" ? 330 : 500
+ Image {
+ source: Style.symbol("RectangleGradient256x512")
+ anchors.fill: parent
+ }
+ Tool {
+ vspan: 2
+ z: 3
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottomMargin: 120
+ name: {
+ if (root.modelType === "Music")
+ active ? "video-pause" : "video-play"
+ else
+ "video-play"
+ }
+ onClicked: {
+ if (root.modelType === "Music") {
+ active ? MusicService.pause() : MusicService.play()
+ if (MusicProvider.currentIndex !== index) {
+ active ? MusicService.pause() : MusicService.play()
+ MusicProvider.currentIndex = index
+ }
+ }
+ else {
+ MusicService.pause()
+ MovieProvider.currentIndex = index
+ root.showCurrentTrack()
+ }
+ }
+ active: MusicProvider.currentIndex === index && MusicService.playing
+ }
+ Image {
+ z: 2
+ source: Style.symbol('MusicOverlayGradient')
+ anchors.fill: parent
+ }
+
+ Text {
+ z: 2
+ width: 300
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: coverImage.bottom
+ anchors.bottomMargin: Style.padding
+ maximumLineCount: 2
+ text: model.title
+ color: Style.colorWhite
+ wrapMode: Text.WordWrap
+ font.pixelSize: Style.fontSizeS
+ horizontalAlignment: Text.AlignHCenter
+ visible: modelType === "Music"
+ }
+ Image {
+ id: coverImage
+ source: modelType === "Music" ? MusicProvider.coverPath(model.cover) : MovieProvider.coverPath(model.cover)
+ width: parent.width
+ fillMode: Image.PreserveAspectFit
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+ }
+
+
+ LaunchItemBackground {
+ id: musicLibrary
+ text: "Music"
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ anchors.margins: Style.padding
+ height: 226
+ width: Style.launchBarHeight
+ scale: musicArea.pressed?0.85:1.0
+
+ Image {
+ source: Style.symbol("music")
+ anchors.centerIn: parent
+ }
+
+ MouseArea {
+ id: musicArea
+ anchors.fill: parent
+ onClicked: {
+ root.modelType = "Music"
+ }
+ }
+
+
+ Component.onCompleted: MusicProvider.selectRandomTracks()
+ }
+
+ LaunchItemBackground {
+ text: "Movies"
+
+ anchors.left: musicLibrary.right
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.margins: Style.padding
+ height: 226
+ width: Style.launchBarHeight
+ scale: movieArea.pressed?0.85:1.0
+
+ Image {
+ source: Style.symbol("video")
+ anchors.centerIn: parent
+ }
+
+ MouseArea {
+ id: movieArea
+ anchors.fill: parent
+ onClicked: {
+ root.modelType = "Movies"
+ }
+ }
+ Component.onCompleted: MovieProvider.selectRandom()
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/ClusterWidget.qml b/CenterConsole/apps/com.pelagicore.media/ClusterWidget.qml
new file mode 100644
index 0000000..58dbcc1
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/ClusterWidget.qml
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import "."
+import utils 1.0
+
+Item {
+ id: musicContainer
+
+ property url currentCover: MusicProvider.currentCover
+ property string currentSong: MusicProvider.currentEntry.title
+ property string currentArtist: MusicProvider.currentEntry.artist
+ opacity: 0.5
+ property int defaultYPos: 0//400
+ y: defaultYPos
+
+ Image {
+ id: image
+ width: 354
+ height: 354
+ source: "ClusterWidgetGradient.png"
+
+ Image {
+ anchors.margins: 60
+ fillMode: Image.PreserveAspectCrop
+ anchors.fill: parent
+ asynchronous: true
+ source: currentCover
+ }
+ }
+
+ Text {
+ id: title
+ anchors.top: image.bottom
+ anchors.topMargin: -45
+ anchors.horizontalCenter: image.horizontalCenter
+ text: currentSong
+ color: "gray"
+ font.pixelSize: 10
+ }
+
+ Text {
+ anchors.top: title.bottom
+ anchors.horizontalCenter: image.horizontalCenter
+ text: currentArtist
+ color: "lightGray"
+ font.pixelSize: 10
+ }
+
+ Timer {
+ id: fadeOutTimer
+ interval: 3000
+ running: false
+ repeat: false
+ onTriggered: {
+ fadeOut.start()
+ }
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeIn
+ to: 1.0
+ duration: 500
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeOut
+ to: 0.5
+ duration: 500
+ }
+
+ // TODO: Find out why these commented-out animations cause flashing on HW, and fix it
+// PropertyAnimation on y {
+// id: startupAnimation
+// to: 0
+// duration: 500
+// easing.type: Easing.InCubic
+// }
+
+ Component.onCompleted: {
+// startupAnimation.start()
+// fadeIn.start()
+// fadeOutTimer.start()
+ }
+
+ onCurrentCoverChanged: {
+ fadeIn.start()
+ fadeOutTimer.restart()
+ }
+
+ onCurrentSongChanged: {
+ fadeIn.start()
+ fadeOutTimer.restart()
+ }
+
+ onVisibleChanged: {
+ if (visible) {
+// y = defaultYPos
+// startupAnimation.start()
+ fadeIn.start()
+ fadeOutTimer.restart()
+ }
+ }
+}
+
diff --git a/CenterConsole/apps/com.pelagicore.media/ClusterWidgetGradient.png b/CenterConsole/apps/com.pelagicore.media/ClusterWidgetGradient.png
new file mode 100644
index 0000000..634f569
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/ClusterWidgetGradient.png
Binary files differ
diff --git a/CenterConsole/apps/com.pelagicore.media/CoverItem.qml b/CenterConsole/apps/com.pelagicore.media/CoverItem.qml
new file mode 100644
index 0000000..c91bd05
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/CoverItem.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+import QtGraphicalEffects 1.0
+import utils 1.0
+import controls 1.0
+
+UIElement {
+ id: root
+ hspan: 6
+ vspan: 12
+ signal pressed()
+ property alias source: image.source
+ property alias title: title.text
+ property alias subTitle: subTitle.text
+
+ ColumnLayout {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 0
+ Item {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Style.hspan(5)
+ height: width
+ Rectangle {
+ anchors.fill: parent
+ color: Style.colorWhite
+ border.color: Qt.darker(color, 1.2)
+ }
+ Image {
+ id: image
+ anchors.fill: parent
+ anchors.margins: Style.paddingXS
+ fillMode: Image.PreserveAspectCrop
+ asynchronous: true
+ }
+ }
+ Label {
+ id: title
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ font.weight: Font.Light
+ opacity: 0.5
+ }
+ Label {
+ id: subTitle
+ Layout.fillWidth: true
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: Style.fontSizeS
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.pressed()
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/CurrentTrackScreen.qml b/CenterConsole/apps/com.pelagicore.media/CurrentTrackScreen.qml
new file mode 100644
index 0000000..5d84d6c
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/CurrentTrackScreen.qml
@@ -0,0 +1,245 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+
+import controls 1.0
+import utils 1.0
+import service.music 1.0
+import "."
+
+UIScreen {
+ id: root
+ hspan: 24
+ vspan: 24
+
+ title: 'Music'
+
+ property var track: MusicProvider.currentEntry
+ property bool libraryVisible: false
+
+ signal showAlbums()
+
+ Image {
+ id: screenCast
+ source: Style.symbol("screencast")
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.margins: 20
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+
+ }
+ }
+ }
+
+ ColumnLayout {
+ id: musicControl
+ width: Style.screenWidth
+ height: root.height
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 0
+ Spacer {
+ vspan: 2
+ }
+
+ SwipeView {
+ id: pathView
+ itemWidth: Style.screenWidth
+
+ width: Style.screenWidth
+ height: Style.cellHeight * 12
+
+ items: MusicProvider.nowPlaying.model
+
+ currentViewIndex: MusicProvider.currentIndex
+
+ onCurrentViewIndexChanged: MusicProvider.currentIndex = pathView.currentViewIndex
+
+ delegate: CoverItem {
+ z: PathView.z
+ scale: PathView.scale
+ source: MusicProvider.coverPath(model.cover)
+ title: model.title
+ subTitle: model.artist
+ onClicked: {
+ // MusicService.togglePlay()
+ root.showAlbums()
+ }
+ }
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width
+ spacing: 10
+ Label {
+ id: textElement
+ text: MusicService.currentTime
+ }
+
+ Slider {
+ id: slider
+ value: MusicService.position
+ minimum: 0.00
+ maximum: MusicService.duration
+ vspan: 1
+ function valueToString() {
+ return Math.floor(value/60000) + ':' + Math.floor((value/1000)%60)
+ }
+ onActiveValueChanged: {
+ MusicService.seek(activeValue)
+ }
+ }
+
+ Label {
+ text: MusicService.durationTime
+ }
+ }
+
+ RowLayout {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 0
+ Tool {
+ hspan: 2
+ name: 'video-previous'
+ onClicked: MusicService.previousTrack()
+ size: Style.symbolSizeXS
+ }
+ Spacer { hspan: 2 }
+ Tool {
+ hspan: 2
+ name: MusicService.playing?'video-pause':'video-play'
+ onClicked: MusicService.togglePlay()
+ }
+ Spacer { hspan: 2 }
+ Tool {
+ hspan: 2
+ name: 'video-next'
+ onClicked: MusicService.nextTrack()
+ size: Style.symbolSizeXS
+ }
+ }
+ Spacer {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+
+ Library {
+ id: library
+ x: parent.width
+ opacity: 0
+ visible: opacity > 0
+ onClose: {
+ root.libraryVisible = false
+ }
+ }
+
+ UIElement {
+ id: sourceOption
+ hspan: 4
+ vspan: 12
+ anchors.right: musicControl.left
+ anchors.rightMargin: 60
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: -60
+
+ Column {
+ spacing: 1
+ Button_neptune {
+ hspan: 4
+ vspan: 4
+ text: "BLUETOOTH"
+ label.font.pixelSize: Style.fontSizeL
+ }
+ Button_neptune {
+ hspan: 4
+ vspan: 4
+ text: "USB"
+ enabled: false
+ label.font.pixelSize: Style.fontSizeL
+ }
+ Button_neptune {
+ hspan: 4
+ vspan: 4
+ text: "SPOTIFY"
+ enabled: false
+ label.font.pixelSize: Style.fontSizeL
+ }
+ }
+ }
+
+ Component.onCompleted: MusicProvider.selectRandomTracks()
+
+ states: State {
+ name: "libaryMode"; when: root.libraryVisible
+
+ PropertyChanges {
+ target: library
+ opacity: 1
+ x: root.width - library.width
+ }
+
+ PropertyChanges {
+ target: libraryButton
+ opacity: 0
+ }
+
+ PropertyChanges {
+ target: sourceOption
+ opacity: 0
+ }
+
+ AnchorChanges {
+ target: musicControl
+ anchors.horizontalCenter: undefined
+ }
+
+ PropertyChanges {
+ target: musicControl
+ x: 0
+ }
+ }
+
+ transitions: Transition {
+ from: ""; to: "libaryMode"; reversible: true
+
+ ParallelAnimation {
+ NumberAnimation { target: library; properties: "opacity"; duration: 400 }
+ NumberAnimation { target: library; properties: "x"; duration: 300 }
+ NumberAnimation { target: libraryButton; properties: "opacity"; duration: 300 }
+ NumberAnimation { target: sourceOption; properties: "opacity"; duration: 300 }
+ NumberAnimation { target: musicControl; properties: "x"; duration: 300 }
+ }
+ }
+
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/Library.qml b/CenterConsole/apps/com.pelagicore.media/Library.qml
new file mode 100644
index 0000000..7896ffa
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/Library.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+
+import controls 1.0
+import utils 1.0
+import "."
+
+UIElement {
+ id: root
+ hspan: 12
+ vspan: 22
+
+ signal close()
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+ }
+
+
+ LibraryList {
+ id: nowPlaying
+ visible: false
+ nowPlaying: true
+ }
+
+ LibraryList {
+ id: library
+ visible: false
+ }
+}
+
diff --git a/CenterConsole/apps/com.pelagicore.media/LibraryList.qml b/CenterConsole/apps/com.pelagicore.media/LibraryList.qml
new file mode 100644
index 0000000..3906024
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/LibraryList.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+
+import controls 1.0
+import utils 1.0
+import service.music 1.0
+import "."
+
+UIElement {
+ id: root
+ hspan: 10
+ vspan: 18
+
+ property string type: ""
+ property bool nowPlaying: false
+
+ onTypeChanged: {
+ if (type === "songs")
+ MusicProvider.querySongs()
+ else if (type === "artists")
+ MusicProvider.queryArtists()
+ else if (type === "albums")
+ MusicProvider.queryAllAlbums()
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+ }
+
+ ListView {
+ id: listView
+ anchors.fill: parent
+ anchors.topMargin: 10
+ model: root.nowPlaying ? MusicProvider.nowPlaying.model : MusicProvider.musicLibrary.model
+ clip: true
+ highlightMoveDuration: 300
+ highlightFollowsCurrentItem: false
+ currentIndex: MusicProvider.currentIndex
+
+ delegate: UIElement {
+ hspan: root.hspan
+ vspan: 3
+
+ Rectangle {
+ anchors.fill: parent
+ opacity: 0.2
+ visible: listView.currentIndex === index
+ }
+
+ Rectangle {
+ width: parent.width
+ height: 1
+ opacity: 0.2
+ color: "white"
+ }
+
+ Row {
+ anchors.verticalCenter: parent.verticalCenter
+ Icon {
+ hspan: 2
+ vspan: hspan
+ anchors.verticalCenter: parent.verticalCenter
+ fit: true
+ source: MusicProvider.coverPath(model.cover)
+ }
+
+ Column {
+ Label {
+ text: root.type === "albums" ? model.album.toUpperCase() : model.title.toUpperCase()
+ font.pixelSize: Style.fontSizeM
+ }
+ Label {
+ text: model.artist.toUpperCase()
+ font.bold: true
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (root.nowPlaying) {
+ MusicProvider.currentIndex = index
+ }
+ else {
+ listView.currentIndex = index
+ if (root.type === "songs") {
+ MusicProvider.selectSpecSong()
+ MusicProvider.currentIndex = index
+ }
+ else if (root.type === "artists")
+ MusicProvider.querySpecArtist(model.artist)
+ else if (root.type === "albums")
+ MusicProvider.querySpecAlbum(model.album)
+ }
+ MusicService.play()
+ }
+ }
+ }
+
+ Rectangle {
+ width: parent.width
+ height: 300
+ anchors.bottom: parent.bottom
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "transparent" }
+ GradientStop { position: 1.0; color: "black" }
+ }
+ }
+ }
+
+}
+
diff --git a/CenterConsole/apps/com.pelagicore.media/MediaSelectionWidget.qml b/CenterConsole/apps/com.pelagicore.media/MediaSelectionWidget.qml
new file mode 100644
index 0000000..681e3ce
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/MediaSelectionWidget.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+import service.movie 1.0
+import controls 1.0
+import "."
+
+Item {
+ id: musicLibrary
+ height: Style.launchBarHeight / 2
+ width: 512
+ anchors.margins: Style.padding
+ anchors.rightMargin: Style.paddingXXL
+ property alias model: repeater.model
+ property string modelType
+
+
+ Image {
+ source: Style.symbol("RectangleGradient256x512")
+ }
+
+ Image {
+ z: 2
+ source: Style.symbol("MusicOverlayGradient2")
+ }
+
+ Label {
+ id: title
+ z: 3
+ text: modelType
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: Style.paddingXXL
+ }
+
+ Grid {
+ anchors.top: parent.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ rows: 2
+ columns: 4
+ Repeater {
+ id: repeater
+
+ delegate: Item {
+ width: musicLibrary.width/4
+ height: musicLibrary.height/2
+ Image {
+ source: modelType === "Music" ? MusicProvider.coverPath(model.cover) : MovieService.coverPath(model.cover)
+ anchors.fill: parent
+ }
+ }
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked:
+ root.modelType = modelType
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/MoviePlayer.qml b/CenterConsole/apps/com.pelagicore.media/MoviePlayer.qml
new file mode 100644
index 0000000..aa7ada6
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/MoviePlayer.qml
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+import QtQuick.Controls 1.0
+import QtMultimedia 5.0
+import QtGraphicalEffects 1.0
+
+import controls 1.0
+import utils 1.0
+import "."
+
+UIScreen {
+ id: root
+ hspan: 24
+ vspan: 24
+
+ title: 'Movies'
+
+ property bool active: false
+ property bool hideControls: false
+
+ property var track: MovieProvider.currentEntry
+
+ onBackScreen: {
+ video.stop()
+ MovieProvider.state = MediaPlayer.StoppedState
+ }
+
+ Video {
+ id: video
+ anchors.fill: parent
+ source: MovieProvider.sourcePath(root.track.source)
+ autoPlay: true
+ property bool running: playbackState === MediaPlayer.PlayingState
+
+ function togglePlay() {
+ if (running) {
+ pause()
+ } else {
+ play()
+ }
+ }
+ onPlaybackStateChanged: {
+ MovieProvider.state = playbackState
+ }
+ }
+
+ Rectangle {
+ anchors.fill: toolBar
+ anchors.margins: -Style.paddingL
+ color: '#000'
+ opacity: toolBar.opacity * 0.85
+ radius: Style.buttonRadius
+ }
+ ColumnLayout {
+ id: toolBar
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: Style.vspan(4)
+ spacing: 0
+ opacity: root.hideControls?0.0:1.0
+ Behavior on opacity {
+ NumberAnimation { duration: 1000 }
+ }
+ RowLayout {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: Style.hspan(2)
+ Tool {
+ name: 'video-previous'
+ onClicked: MovieProvider.previous()
+ }
+ Tool {
+ name: video.running?'video-pause':'video-play'
+ onClicked: video.togglePlay()
+ }
+ Tool {
+ name: 'video-next'
+ onClicked: MovieProvider.next()
+ }
+ }
+ Slider {
+ anchors.horizontalCenter: parent.horizontalCenter
+ value: video.position
+ minimum: 0.00
+ maximum: video.duration
+ vspan: 1
+ function valueToString() {
+ return Math.floor(value/60000) + ':' + Math.floor((value/1000)%60)
+ }
+ onActiveValueChanged: {
+ video.seek(activeValue)
+ MovieProvider.seek = activeValue
+ }
+ }
+ }
+
+ MouseArea {
+ id: clickOverlay
+ anchors.fill: parent
+ onClicked: {
+ root.hideControls = false
+ enabled = false
+ hideTimer.start()
+ }
+ }
+
+ Timer {
+ id: hideTimer
+ interval: 5000
+ running: video.running
+ onTriggered: {
+ root.hideControls = true
+ clickOverlay.enabled = true
+ }
+ }
+
+ Component.onDestruction: {
+ // required to avoid crashing qmllive
+ video.source = ''
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/MovieProvider.qml b/CenterConsole/apps/com.pelagicore.media/MovieProvider.qml
new file mode 100644
index 0000000..f506957
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/MovieProvider.qml
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.1
+import com.pelagicore.datasource 1.0
+import service.movie 1.0
+
+SqlQueryDataSource {
+ id: root
+ database: "media"
+
+ property url filePrefix: "file:///"
+ property int currentIndex: 0
+ property var currentEntry: get(currentIndex);
+ property url currentSource: filePrefix + storageLocation + '/media/movies/' + currentEntry.source
+ property url currentCover: filePrefix + storageLocation + '/media/movies/' + currentEntry.cover
+
+ /*
+ MediaPlayer.PlayingState 1 - the media is playing
+ MediaPlayer.PausedState 2 - the media is paused
+ MediaPlayer.StoppedState 0 - the media is stopped*/
+ //Create playing state and seek to share between views
+ property int state: 0
+ property int seek: 0
+
+ function selectRandom() {
+ root.currentIndex = -1
+ query = 'select * from movies order by random()'
+ root.currentIndex = 0
+ }
+
+ function coverPath(cover) {
+ return Qt.resolvedUrl(filePrefix + storageLocation + '/media/movies/' + cover)
+ }
+
+ function sourcePath(source) {
+ return Qt.resolvedUrl(filePrefix + storageLocation + '/media/movies/' + source)
+ }
+
+ function next() {
+ print('$movies.nextTrack()')
+ root.currentIndex++
+ }
+
+ function previous() {
+ print('$movies.previousTrack()')
+ root.currentIndex--
+ }
+
+ Component.onCompleted: {
+ MovieService.movieProvider = root
+ MovieService.trackCount = Qt.binding(function() { return root.count})
+ MovieService.currentTrack = Qt.binding(function() { return root.get(root.currentIndex)})
+ MovieService.currentIndex = Qt.binding(function() { return root.currentIndex})
+ print("*******************Movie provider completed")
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/Music.qml b/CenterConsole/apps/com.pelagicore.media/Music.qml
new file mode 100644
index 0000000..868a387
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/Music.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+import controls 1.0
+import utils 1.0
+import "."
+import com.pelagicore.ScreenManager 1.0
+
+AppUIScreen {
+ id: root
+ title: "Neptune Music Player"
+
+ onClusterKeyPressed: {
+ if (key === Qt.Key_Down) {
+ MusicProvider.next()
+ }
+ else if (key === Qt.Key_Up) {
+ MusicProvider.previous()
+ }
+ }
+
+ Component.onCompleted: {
+ if (ScreenManager.screenCount() > 1) {
+ clusterComponent = Qt.createComponent("ClusterWidget.qml")
+ } else {
+ console.log("Cannot show widget in cluster")
+ }
+ if (clusterComponent.status === Component.Ready) {
+ cluster = clusterComponent.createObject(root)
+ }
+ }
+ passenger: PassengerWidget {}
+
+ AppStackView {
+ id: stack
+ anchors.fill: parent
+ initialItem: albums
+
+ Component {
+ id: albums
+ AlbumScreen {
+ onBackScreen: {
+ root.back()
+ }
+ onShowCurrentTrack: {
+ stack.push(moviePlayer)
+ }
+ }
+ }
+ Component {
+ id: moviePlayer
+ MoviePlayer {
+ onBackScreen: {
+ stack.pop()
+ }
+ }
+ }
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/MusicProvider.qml b/CenterConsole/apps/com.pelagicore.media/MusicProvider.qml
new file mode 100644
index 0000000..2df9e8c
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/MusicProvider.qml
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.1
+import QtApplicationManager 1.0
+import com.pelagicore.datasource 1.0
+import service.music 1.0
+
+QtObject {
+ id: root
+
+ property SqlQueryDataSource musicLibrary: SqlQueryDataSource {
+ database: "media"
+ query: 'select * from music'
+ }
+
+ property SqlQueryDataSource nowPlaying: SqlQueryDataSource {
+ database: "media"
+ query: 'select * from music'
+ }
+
+ property int currentIndex: 0
+ property int count: nowPlaying.count
+ onCountChanged: {
+ currentIndex = 0
+ }
+
+
+ property url filePrefix: "file:///"
+
+ property var currentEntry: nowPlaying.get(currentIndex)
+ property url currentSource: filePrefix + nowPlaying.storageLocation + '/media/music/' + currentEntry.source
+ property url currentCover: filePrefix + nowPlaying.storageLocation + '/media/music/' + currentEntry.cover
+
+ function queryAllAlbums() {
+ musicLibrary.query = 'select * from music group by album'
+ }
+
+ function querySongs() {
+ musicLibrary.query = 'select distinct * from music'
+ }
+
+ function queryArtists() {
+ musicLibrary.query = 'select * from music group by artist'
+ }
+
+ function querySpecArtist(artist) {
+ nowPlaying.query = "select distinct * from music where artist='" + artist + "'"
+ }
+
+ function querySpecAlbum(album) {
+ nowPlaying.query = "select distinct * from music where album='" + album + "'"
+ }
+
+ function selectSpecSong () {
+ nowPlaying.query = 'select distinct * from music'
+ }
+
+ function selectRandomTracks() {
+ nowPlaying.query = 'select distinct * from music order by random()'
+ // TODO: currentIndex should be updated, otherwise currentEntry is initially wrong
+ // TODO: Let's just do this hack, it will fix the issues..
+ next()
+ }
+
+ function selectRecentTracks() {
+ nowPlaying.query = 'select distinct * from music order by random() limit 8'
+ }
+
+ function coverPath(cover) {
+ return Qt.resolvedUrl(filePrefix + root.nowPlaying.storageLocation + '/media/music/' + cover)
+ }
+
+ function sourcePath(source) {
+ return Qt.resolvedUrl(filePrefix + root.nowPlaying.storageLocation + '/media/music/' + source)
+ }
+
+ function next() {
+ print('MusicService.nextTrack()')
+ if (root.currentIndex < root.count - 1)
+ currentIndex++
+ }
+
+ function previous() {
+ print('MusicService.previousTrack()')
+ if (currentIndex > 0)
+ currentIndex--
+ }
+
+ function initialize() {
+ MusicService.musicProvider = root
+ MusicService.currentIndex = Qt.binding(function() { return root.currentIndex})
+ MusicService.currentTrack = Qt.binding(function() { return root.currentEntry})
+ MusicService.trackCount = Qt.binding(function() { return root.nowPlaying.count})
+ MusicService.coverPath = Qt.binding(function() { return root.currentCover})
+ MusicService.url = Qt.binding(function() { return root.currentSource})
+ }
+
+
+ property Item ipc: Item {
+ ApplicationInterfaceExtension {
+ id: musicRemoteControl
+
+ name: "com.pelagicore.music.control"
+ }
+
+ Binding { target: musicRemoteControl.object; property: "currentTrack"; value: MusicService.currentTrack }
+ Binding { target: musicRemoteControl.object; property: "currentTime"; value: MusicService.currentTime }
+ Binding { target: musicRemoteControl.object; property: "durationTime"; value: MusicService.durationTime }
+ Binding { target: musicRemoteControl.object; property: "playing"; value: MusicService.playing }
+ Binding { target: musicRemoteControl.object; property: "currentCover"; value: MusicService.coverPath }
+
+ Connections {
+ target: musicRemoteControl.object
+
+ onPlay: {
+ MusicService.musicPlay()
+ }
+
+ onPause: {
+ MusicService.pause()
+ }
+
+ onPreviousTrack: {
+ MusicService.previousTrack()
+ }
+
+ onNextTrack: {
+ MusicService.nextTrack()
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ initialize()
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/PassengerWidget.qml b/CenterConsole/apps/com.pelagicore.media/PassengerWidget.qml
new file mode 100644
index 0000000..1929143
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/PassengerWidget.qml
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.0
+import QtQuick.Layouts 1.0
+import QtMultimedia 5.0
+
+import utils 1.0
+import controls 1.0
+import service.music 1.0
+import "."
+
+Item {
+ id: musicContainer
+ property url currentCover: MusicProvider.currentCover
+ property var track: MovieProvider.currentEntry
+ property int state: MovieProvider.state
+ property int seek: MovieProvider.seek
+
+ width: Style.screenHeight
+ height: Style.screenWidth
+
+ Image {
+ id: image
+ anchors.centerIn: parent
+ asynchronous: true
+ source: MusicProvider.currentCover
+ }
+
+ onStateChanged: {
+ if (state == MediaPlayer.PlayingState) {
+ video.play()
+ } else if (state == MediaPlayer.PausedState){
+ video.pause()
+ } else {
+ video.stop()
+ }
+ }
+ onSeekChanged: video.seek(seek)
+
+ Video {
+ id: video
+ visible: state === MediaPlayer.StoppedState ? false : true
+ anchors.fill: parent
+ source: MovieProvider.sourcePath(musicContainer.track.source)
+ property bool running: state === MediaPlayer.PlayingState
+ }
+}
+
diff --git a/CenterConsole/apps/com.pelagicore.media/PlaylistContainer.qml b/CenterConsole/apps/com.pelagicore.media/PlaylistContainer.qml
new file mode 100644
index 0000000..deee005
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/PlaylistContainer.qml
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Layouts 1.0
+import utils 1.0
+import controls 1.0
+import "."
+
+RowLayout {
+ id: playListContainer
+
+ signal pressed(int index)
+
+ spacing: 5
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.topMargin: Style.vspan(1)
+ height: Style.vspan(16)
+ width: Style.hspan(5)
+ anchors.rightMargin: expanded ? Style.hspan(0) : -Style.hspan(4)
+ Behavior on anchors.rightMargin {
+ NumberAnimation { easing.type: Easing.InCirc; duration: 250 }
+ }
+
+ property bool expanded: false
+
+ function toggleExpand() {
+ expanded = !expanded
+ }
+
+ Tool {
+ name: 'music'
+ Layout.alignment: Qt.AlignTop
+ onClicked: {
+ playListContainer.toggleExpand()
+ }
+ }
+ Timer {
+ id: closer
+ interval: 3000
+ onTriggered: {
+ playListContainer.expanded = false
+ }
+ }
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ color: '#000'
+ anchors.margins: -Style.padding
+ ListView {
+ id: playListView
+ anchors.fill: parent
+ clip: true
+ model: MusicProvider.model
+ currentIndex: MusicProvider.currentIndex
+ highlight: Rectangle {
+ color: Style.colorWhite; opacity: 0.25
+ border.color: Qt.lighter(color, 1.2)
+ }
+ highlightMoveDuration: 75
+ delegate: UIElement {
+ hspan: 5
+ vspan: 2
+ RowLayout {
+ anchors.fill: parent
+ spacing: 0
+ Item {
+ Layout.fillHeight: true
+ width: Style.hspan(1)
+ Item {
+ anchors.fill: parent
+ anchors.margins: Style.padding
+ Rectangle {
+ anchors.fill: parent
+ anchors.leftMargin: -6
+ anchors.rightMargin: -6
+ anchors.topMargin: -2
+ anchors.bottomMargin: -2
+ color: Style.colorWhite
+ }
+
+ Image {
+ anchors.centerIn: parent
+ height: parent.height
+ width: parent.height
+ source: MusicProvider.coverPath(model.cover)
+ fillMode: Image.PreserveAspectCrop
+ asynchronous: true
+ }
+ }
+ }
+ ColumnLayout {
+ spacing: 0
+ Label {
+ text: model.title
+ font.pixelSize: Style.fontSizeXS
+ opacity: 0.5
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ }
+ Label {
+ text: model.artist
+ Layout.fillWidth: true
+ elide: Text.ElideRight
+ }
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ playListContainer.pressed(index)
+ closer.restart()
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/CenterConsole/apps/com.pelagicore.media/icon.png b/CenterConsole/apps/com.pelagicore.media/icon.png
new file mode 100644
index 0000000..77bd3df
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/icon.png
Binary files differ
diff --git a/CenterConsole/apps/com.pelagicore.media/info.yaml b/CenterConsole/apps/com.pelagicore.media/info.yaml
new file mode 100644
index 0000000..33baf2f
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/info.yaml
@@ -0,0 +1,12 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'com.pelagicore.media'
+icon: 'icon.png'
+code: 'Music.qml'
+runtime: 'qml'
+name:
+ en: 'Music'
+ de: 'Musik'
+
+categories: [ 'app', 'media' ]
diff --git a/CenterConsole/apps/com.pelagicore.media/qmldir b/CenterConsole/apps/com.pelagicore.media/qmldir
new file mode 100644
index 0000000..50d659d
--- /dev/null
+++ b/CenterConsole/apps/com.pelagicore.media/qmldir
@@ -0,0 +1,3 @@
+singleton MusicProvider 1.0 MusicProvider.qml
+singleton MovieProvider 1.0 MovieProvider.qml
+
diff --git a/CenterConsole/apps/com.qtcompany.calendar/Calendar.qml b/CenterConsole/apps/com.qtcompany.calendar/Calendar.qml
new file mode 100644
index 0000000..77776fb
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.calendar/Calendar.qml
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Controls 1.4
+import QtQuick.Layouts 1.1
+import QtQuick.Controls.Styles 1.4
+import controls 1.0
+import utils 1.0
+import "."
+import com.pelagicore.ScreenManager 1.0
+
+AppUIScreen {
+ id: root
+ title: "Calendar"
+
+ Component.onCompleted: {
+ if (ScreenManager.screenCount() > 1) {
+ clusterComponent = Qt.createComponent("ClusterWidget.qml")
+ } else {
+ console.log("Cannot show widget in cluster")
+ }
+ if (clusterComponent.status === Component.Ready) {
+ cluster = clusterComponent.createObject(root, {"appointment": "No appointments"})
+ }
+ }
+
+ UIScreen {
+ width: Style.screenWidth
+ height: Style.screenHeight - Style.bottomBarHeight - Style.statusBarHeight
+ onBackScreen: root.back()
+ title: "Calendar"
+ Calendar {
+ weekNumbersVisible: false
+ width: root.width - 150
+ height: root.height - 150
+ x: 75
+ y: 75
+ style: CalendarStyle {
+ gridVisible: false
+ gridColor: "transparent"
+ background: Rectangle {
+ color: "transparent"
+ }
+
+ dayOfWeekDelegate: Item {
+ implicitHeight: control.height * 0.13
+
+ Label {
+ text: localeDayName.length == 0 || localeDayName.length > 1
+ ? control.__locale.dayName(styleData.dayOfWeek, Locale.ShortFormat)
+ : localeDayName
+
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+
+ property string localeDayName: control.__locale.dayName(styleData.dayOfWeek, Locale.NarrowFormat)
+ }
+ }
+
+ dayDelegate: Rectangle {
+ color: "transparent"
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 2
+ gradient: Gradient {
+ GradientStop {
+ position: 0.0
+ color: styleData.selected ? "#666" : (styleData.visibleMonth && styleData.valid ? "#333" : "#111");
+ }
+ GradientStop {
+ position: 1.00
+ color: "transparent";
+ }
+ }
+ Label {
+ text: styleData.date.getDate()
+ color: styleData.valid ? "white" : "grey"
+ }
+ }
+ }
+ navigationBar: Rectangle {
+ implicitHeight: Math.round(control.height * 0.1)
+ color: "transparent"
+ RowLayout {
+ anchors.fill: parent
+ Text {
+ id: prevButton
+ text: "\u25c0" // LEFT-POINTING TRIANGLE
+ font.pixelSize: Style.fontSizeXXS
+ color: "white"
+ MouseArea {
+ anchors.fill: parent
+ onClicked: control.showPreviousMonth()
+ }
+ }
+ Label {
+ id: dateText
+ Layout.alignment: Qt.AlignCenter
+ text: styleData.title
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: Style.fontSizeL
+ }
+ Text {
+ id: nextButton
+ Layout.alignment: Qt.AlignRight
+ text: "\u25b6" // RIGHT-POINTING TRIANGLE
+ font.pixelSize: Style.fontSizeXXS
+ color: "white"
+ MouseArea {
+ anchors.fill: parent
+ onClicked: control.showNextMonth()
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/CenterConsole/apps/com.qtcompany.calendar/ClusterWidget.qml b/CenterConsole/apps/com.qtcompany.calendar/ClusterWidget.qml
new file mode 100644
index 0000000..0810ab8
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.calendar/ClusterWidget.qml
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import utils 1.0
+
+Item {
+ id: calendarContainer
+ property string appointment
+ property var currentDate
+ property string date
+ property string time
+ opacity: 0.5
+ property int defaultXPos: 0
+ x: defaultXPos
+
+ Image {
+ id: image
+ width: 100
+ height: 100
+ source: Style.symbol("calendar")
+ x: 50
+ }
+
+ Text {
+ id: dateText
+ anchors.top: image.bottom
+ anchors.topMargin: 10
+ text: date
+ color: "gray"
+ font.pixelSize: 16
+ }
+
+ Text {
+ id: timeText
+ anchors.top: dateText.bottom
+ anchors.horizontalCenter: dateText.horizontalCenter
+ text: time
+ color: "gray"
+ font.pixelSize: 36
+ }
+
+ Text {
+ anchors.top: timeText.bottom
+ anchors.horizontalCenter: dateText.horizontalCenter
+ text: appointment
+ color: "lightGray"
+ font.pixelSize: 20
+ }
+
+ Timer {
+ id: fadeOutTimer
+ interval: 5000
+ running: false
+ repeat: false
+ onTriggered: {
+ fadeOut.start()
+ }
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeIn
+ to: 1.0
+ duration: 500
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeOut
+ to: 0.5
+ duration: 500
+ }
+
+ // TODO: Find out why these commented-out animations cause flashing on HW, and fix it
+// PropertyAnimation on x {
+// id: startupAnimation
+// to: 0
+// duration: 500
+// easing.type: Easing.InCubic
+// }
+
+ Component.onCompleted: {
+ currentDate = new Date()
+ date = currentDate.toLocaleDateString(Qt.locale("en_GB"))
+ time = currentDate.toLocaleTimeString(Qt.locale("en_GB"), "hh:mm")
+// startupAnimation.start()
+// fadeIn.start()
+// fadeOutTimer.start()
+ }
+
+ onVisibleChanged: {
+ if (visible) {
+ currentDate = new Date()
+ date = currentDate.toLocaleDateString(Qt.locale("en_GB"))
+ time = currentDate.toLocaleTimeString(Qt.locale("en_GB"), "hh:mm")
+// x = defaultXPos
+// startupAnimation.start()
+ fadeIn.start()
+ fadeOutTimer.restart()
+ }
+ }
+}
+
diff --git a/CenterConsole/apps/com.qtcompany.calendar/icon.png b/CenterConsole/apps/com.qtcompany.calendar/icon.png
new file mode 100644
index 0000000..a4cf9a0
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.calendar/icon.png
Binary files differ
diff --git a/CenterConsole/apps/com.qtcompany.calendar/info.yaml b/CenterConsole/apps/com.qtcompany.calendar/info.yaml
new file mode 100644
index 0000000..6ec73ae
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.calendar/info.yaml
@@ -0,0 +1,13 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'com.qtcompany.calendar'
+icon: 'icon.png'
+code: 'Calendar.qml'
+runtime: 'qml'
+
+name:
+ en: 'Calendar'
+ de: 'Kalender'
+
+categories: [ 'app', 'calendar' ]
diff --git a/CenterConsole/apps/com.qtcompany.carinfo/CarInfoField.qml b/CenterConsole/apps/com.qtcompany.carinfo/CarInfoField.qml
new file mode 100644
index 0000000..48415f9
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.carinfo/CarInfoField.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import controls 1.0
+import utils 1.0
+
+Column {
+ spacing: 20
+
+ property string value: ""
+ property string title: ""
+ property string unit: "KM"
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ Label {
+ text: value
+ font.pixelSize: Style.fontSizeL
+ }
+ Label {
+ text: unit
+ font.pixelSize: Style.fontSizeXXS
+ }
+ }
+ Label {
+ text: title
+ font.pixelSize: Style.fontSizeXXS
+ horizontalAlignment: Text.AlignHCenter
+ }
+}
diff --git a/CenterConsole/apps/com.qtcompany.carinfo/Carinfo.qml b/CenterConsole/apps/com.qtcompany.carinfo/Carinfo.qml
new file mode 100644
index 0000000..e23096a
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.carinfo/Carinfo.qml
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+import controls 1.0
+import utils 1.0
+import service.valuesource 1.0
+import "."
+import com.pelagicore.ScreenManager 1.0
+
+AppUIScreen {
+ id: root
+ title: "Car info"
+ color: "black"
+
+ Component.onCompleted: {
+ if (ScreenManager.screenCount() > 1) {
+ clusterComponent = Qt.createComponent("ClusterWidget.qml")
+ } else {
+ console.log("Cannot show widget in cluster")
+ }
+ if (clusterComponent.status === Component.Ready) {
+ cluster = clusterComponent.createObject(root, {"total": ValueSource.totalDistance,
+ "sinceLast": ValueSource.kmSinceCharge })
+ }
+ }
+
+ UIScreen {
+ width: Style.screenWidth
+ height: Style.screenHeight - Style.bottomBarHeight - Style.statusBarHeight
+ onBackScreen: root.back()
+ title: "Car info"
+
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.topMargin: 200
+ anchors.leftMargin: 30
+
+ Row {
+ Layout.alignment: Qt.AlignCenter
+ Label {
+ text: "Ready for the road."
+ font.pixelSize: Style.fontSizeXXL
+ }
+ }
+ RowLayout {
+ Layout.alignment: Qt.AlignCenter
+ spacing: 30
+ Rectangle {
+ height: 2
+ color: "white"
+ width: 300
+ }
+ Label {
+ Layout.alignment: Qt.AlignCenter
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignBottom
+ text: "Status"
+ }
+ Rectangle {
+ height: 2
+ color: "white"
+ width: 300
+ }
+ }
+ Row {
+ Layout.alignment: Qt.AlignCenter
+ spacing: 50
+ CarInfoField{ value: ValueSource.totalDistance.toFixed(); title: "Total\ndistance" }
+ CarInfoField{ value: ValueSource.kmSinceCharge; title: "Since last\nCharge" }
+ CarInfoField{ value: ValueSource.avRangePerCharge; title: "Average\nrange/charge" }
+ CarInfoField{ value: ValueSource.energyPerKm; title: "energy/km"; unit: "WH" }
+ }
+ Rectangle {
+ Layout.alignment: Qt.AlignCenter
+ height: 2
+ color: "white"
+ width: 750
+ }
+
+ Image {
+ Layout.alignment: Qt.AlignCenter
+ source: Style.symbol("CarInfo")
+ }
+ }
+ }
+}
diff --git a/CenterConsole/apps/com.qtcompany.carinfo/ClusterWidget.qml b/CenterConsole/apps/com.qtcompany.carinfo/ClusterWidget.qml
new file mode 100644
index 0000000..226c080
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.carinfo/ClusterWidget.qml
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.7
+import utils 1.0
+
+Item {
+ id: carinfoContainer
+
+ property int total: 0
+ property int sinceLast: 0
+ opacity: 0.5
+ property int defaultXPos: 0
+ x: defaultXPos
+
+ Image {
+ id: image
+ width: 265
+ height: 145
+ source: Style.symbol("CarInfo")
+ }
+
+ Row {
+ scale: 0.75
+ spacing: 10
+ anchors.top: image.bottom
+ anchors.horizontalCenter: image.horizontalCenter
+
+ CarInfoField {
+ title: "Total distance"
+ value: total.toString()
+ unit: "km"
+ }
+
+ CarInfoField {
+ title: "Since last\ncharge"
+ value: sinceLast.toString()
+ unit: "km"
+ }
+ }
+
+ Timer {
+ id: fadeOutTimer
+ interval: 5000
+ running: false
+ repeat: false
+ onTriggered: {
+ fadeOut.start()
+ }
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeIn
+ to: 1.0
+ duration: 500
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeOut
+ to: 0.5
+ duration: 500
+ }
+
+ // TODO: Find out why these commented-out animations cause flashing on HW, and fix it
+// PropertyAnimation on x {
+// id: startupAnimation
+// to: 0
+// duration: 500
+// easing.type: Easing.InCubic
+// }
+
+ Component.onCompleted: {
+// startupAnimation.start()
+// fadeIn.start()
+// fadeOutTimer.start()
+ }
+
+ onVisibleChanged: {
+ if (visible) {
+// x = defaultXPos
+// startupAnimation.start()
+ fadeIn.start()
+ fadeOutTimer.restart()
+ }
+ }
+}
+
diff --git a/CenterConsole/apps/com.qtcompany.carinfo/icon.png b/CenterConsole/apps/com.qtcompany.carinfo/icon.png
new file mode 100644
index 0000000..a4cf9a0
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.carinfo/icon.png
Binary files differ
diff --git a/CenterConsole/apps/com.qtcompany.carinfo/info.yaml b/CenterConsole/apps/com.qtcompany.carinfo/info.yaml
new file mode 100644
index 0000000..8d2d61a
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.carinfo/info.yaml
@@ -0,0 +1,13 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'com.qtcompany.carinfo'
+icon: 'icon.png'
+code: 'Carinfo.qml'
+runtime: 'qml'
+name:
+ en: 'Car info'
+ de: 'Auto info'
+
+categories: [ 'app', 'carinfo' ]
+
diff --git a/CenterConsole/apps/com.qtcompany.contacts/ClusterWidget.qml b/CenterConsole/apps/com.qtcompany.contacts/ClusterWidget.qml
new file mode 100644
index 0000000..31a7003
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.contacts/ClusterWidget.qml
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import utils 1.0
+
+Item {
+ id: contactContainer
+ opacity: 0.5
+ property int defaultYPos: 0
+ y: defaultYPos
+ property alias icon: contactImage.source
+ property alias name: contactName.text
+
+ Image {
+ id: contactImage
+ width: 136
+ height: 136
+ }
+
+ Text {
+ id: title
+ anchors.top: contactImage.bottom
+ anchors.horizontalCenter: contactImage.horizontalCenter
+ text: name === "" ? "Browsing\ncontacts" : "Calling"
+ color: "gray"
+ font.pixelSize: 20
+ }
+
+ Text {
+ id: contactName
+ anchors.top: title.bottom
+ anchors.horizontalCenter: contactImage.horizontalCenter
+ color: "lightGray"
+ font.pixelSize: 24
+ }
+
+ Timer {
+ id: fadeOutTimer
+ interval: 5000
+ running: false
+ repeat: false
+ onTriggered: {
+ fadeOut.start()
+ }
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeIn
+ to: 1.0
+ duration: 500
+ }
+
+ PropertyAnimation on opacity {
+ id: fadeOut
+ to: 0.5
+ duration: 500
+ }
+
+ // TODO: Find out why these commented-out animations cause flashing on HW, and fix it
+// PropertyAnimation on y {
+// id: startupAnimation
+// to: 0
+// duration: 500
+// easing.type: Easing.InCubic
+// }
+
+ Component.onCompleted: {
+// startupAnimation.start()
+// fadeIn.start()
+// fadeOutTimer.start()
+ }
+
+ onVisibleChanged: {
+ if (visible) {
+// y = defaultYPos
+// startupAnimation.start()
+ fadeIn.start()
+ fadeOutTimer.restart()
+ }
+ }
+
+ onIconChanged: {
+ fadeIn.start()
+ fadeOutTimer.restart()
+ }
+}
+
diff --git a/CenterConsole/apps/com.qtcompany.contacts/Contacts.qml b/CenterConsole/apps/com.qtcompany.contacts/Contacts.qml
new file mode 100644
index 0000000..247f66f
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.contacts/Contacts.qml
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+
+import controls 1.0
+import utils 1.0
+import "."
+import com.pelagicore.ScreenManager 1.0
+
+AppUIScreen {
+ id: root
+ title: "Contacts"
+
+ onVisibleChanged: {
+ if (visible) {
+ contactList.currentIndex = -1
+ cluster.icon = Style.symbol("contacts")
+ cluster.name = ""
+ }
+ }
+
+
+ Component.onCompleted: {
+ if (ScreenManager.screenCount() > 1) {
+ clusterComponent = Qt.createComponent("ClusterWidget.qml")
+ } else {
+ console.log("Cannot show widget in cluster")
+ }
+ if (clusterComponent.status === Component.Ready) {
+ cluster = clusterComponent.createObject(root,{"icon": Style.symbol("contacts"),
+ "name": "" })
+ }
+ }
+ UIScreen {
+ width: Style.screenWidth
+ height: Style.screenHeight - Style.bottomBarHeight - Style.statusBarHeight
+ onBackScreen: root.back()
+ title: "Contacts"
+ Image {
+ anchors.top: parent.top
+ anchors.topMargin: 100
+ source: Style.symbol("background-contacts")
+ }
+
+ ListView {
+ id: contactList
+ anchors.top: parent.top
+ anchors.topMargin: 200
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.left: parent.left
+ currentIndex: -1
+ highlightFollowsCurrentItem: true
+ spacing: 20
+ clip: true
+ focus: true
+ highlight: Rectangle {
+ color: Style.colorWhite
+ opacity: 0.25
+ border.color: Qt.lighter(color, 1.2)
+ }
+
+ model: ListModel {
+ function populateList() {
+ clear()
+ append({
+ icon: Style.symbol("jane"),
+ name: "Jane",
+ number: "+358 55 555 1234"
+ })
+ append({
+ icon: Style.symbol("john"),
+ name: "John",
+ number: "+358 55 555 4321"
+ })
+ }
+
+ Component.onCompleted: {
+ populateList()
+ }
+ }
+
+ delegate: Item {
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: 1080
+ height: 136
+
+ readonly property string currenticon: contactIcon.source
+ readonly property string currentname: contactName.text
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 50
+
+ Image {
+ id: contactIcon
+ source: icon
+ }
+
+ Column {
+ anchors.verticalCenter: contactIcon.verticalCenter
+ spacing: 5
+
+ Label {
+ id: contactName
+ text: name
+ font.pixelSize: Style.fontSizeL
+ }
+
+ Label {
+ text: number
+ }
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: contactList.currentIndex = index
+ }
+ }
+
+ onCurrentIndexChanged: {
+ cluster.icon = currentItem.currenticon
+ cluster.name = currentItem.currentname
+ }
+ }
+ }
+}
diff --git a/CenterConsole/apps/com.qtcompany.contacts/icon.png b/CenterConsole/apps/com.qtcompany.contacts/icon.png
new file mode 100644
index 0000000..a4cf9a0
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.contacts/icon.png
Binary files differ
diff --git a/CenterConsole/apps/com.qtcompany.contacts/info.yaml b/CenterConsole/apps/com.qtcompany.contacts/info.yaml
new file mode 100644
index 0000000..60827db
--- /dev/null
+++ b/CenterConsole/apps/com.qtcompany.contacts/info.yaml
@@ -0,0 +1,13 @@
+formatVersion: 1
+formatType: am-application
+---
+id: 'com.qtcompany.contacts'
+icon: 'icon.png'
+code: 'Contacts.qml'
+runtime: 'qml'
+name:
+ en: 'Contacts'
+ de: 'Kontakte'
+
+categories: [ 'app', 'contacts' ]
+
diff --git a/CenterConsole/deployment.pri b/CenterConsole/deployment.pri
new file mode 100644
index 0000000..265ce71
--- /dev/null
+++ b/CenterConsole/deployment.pri
@@ -0,0 +1,13 @@
+unix:!android {
+ isEmpty(target.path) {
+ qnx {
+ target.path = /tmp/$${TARGET}/bin
+ } else {
+ target.path = /opt/$${TARGET}/bin
+ }
+ export(target.path)
+ }
+ INSTALLS += target
+}
+
+export(INSTALLS)
diff --git a/CenterConsole/images.qrc b/CenterConsole/images.qrc
new file mode 100644
index 0000000..a45c11b
--- /dev/null
+++ b/CenterConsole/images.qrc
@@ -0,0 +1,25 @@
+<RCC>
+ <qresource prefix="/">
+ <file>assets/icons/seat_left@48.png</file>
+ <file>assets/icons/seat_right@48.png</file>
+ <file>assets/icons/active/seat_left@48.png</file>
+ <file>assets/icons/active/seat_right@48.png</file>
+ <file>assets/icons/arrow@32.png</file>
+ <file>assets/icons/battery@32.png</file>
+ <file>assets/icons/bluetooth@32.png</file>
+ <file>assets/icons/break@32.png</file>
+ <file>assets/icons/clock@48.png</file>
+ <file>assets/icons/information@48.png</file>
+ <file>assets/icons/next@48.png</file>
+ <file>assets/icons/pause@48.png</file>
+ <file>assets/icons/prev@48.png</file>
+ <file>assets/icons/play@48.png</file>
+ <file>assets/icons/search@72.png</file>
+ <file>assets/icons/seat_left@32.png</file>
+ <file>assets/icons/seat_person@72.png</file>
+ <file>assets/icons/seat_right@72.png</file>
+ <file>assets/icons/wifi@32.png</file>
+ <file>assets/drawable-ldpi/appstore_grid_cell_panel.png</file>
+ <file>assets/drawable-ldpi/map_mockup.png</file>
+ </qresource>
+</RCC>
diff --git a/CenterConsole/main.cpp b/CenterConsole/main.cpp
new file mode 100644
index 0000000..95bd674
--- /dev/null
+++ b/CenterConsole/main.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QQuickView>
+
+int main(int argc, char *argv[])
+{
+// qputenv("QML_IMPORT_TRACE", QByteArray("1"));
+ // qputenv("QT_DEBUG_PLUGINS", QByteArray("1"));
+ QGuiApplication app(argc, argv);
+ QQuickView view;
+
+ QObject::connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));
+
+ const char *uri = "CenterConsole";
+ qmlRegisterSingletonType(QUrl("qrc:/qml/Style.qml"), uri, 1, 0, "Style");
+ qmlRegisterSingletonType(QUrl("qrc:/qml/service/climate/ClimateService.qml"), uri, 1, 0, "ClimateService");
+ qmlRegisterSingletonType(QUrl("qrc:/qml/service/settings/SettingsService.qml"), uri, 1, 0, "SettingsService");
+ view.setSource(QUrl(QStringLiteral("qrc:/Main.qml")));
+
+ view.show();
+
+ return app.exec();
+}
diff --git a/CenterConsole/plugins/clusterdatasource/clusterdatabackend.cpp b/CenterConsole/plugins/clusterdatasource/clusterdatabackend.cpp
new file mode 100644
index 0000000..43edf93
--- /dev/null
+++ b/CenterConsole/plugins/clusterdatasource/clusterdatabackend.cpp
@@ -0,0 +1,736 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "clusterdatabackend.h"
+
+#include <QDebug>
+#include <QtGlobal>
+#include <QHostAddress>
+#include <QNetworkInterface>
+
+#ifndef CLUSTERDATA_SIMULATION
+// #define DEBUG_CAN
+#include <QtMath>
+#include <QCanBus>
+#define SOCKETCAN "socketcan"
+#define CANINTERFACE "can0"
+
+// J1939 PGNs
+#define PGN_65268 0xFEF4 // Tire Condition - TIRE
+#define PGN_64933 0xFDA5 // Door Control 2 - DC2
+#define PGN_64972 0xFDCC // Light Control
+#define PGN_61445 0xF005 // Electronic Transmission Controller 2 - ETC2
+#define PGN_65265 0xFEF1 // Cruise Control/Vehicle Speed - CCVS
+#define PGN_65267 0xFEF3 // vehicle position - VP
+#define PGN_65256 0xFEE8 // vehicle direction/speed
+#define PGN_65262 0xFEEE // Engine Temperature 1 - ET1
+#define PGN_65263 0xFEEF // Engine Fluid Level/Pressure 1 - EFL/P1
+#define PGN_65271 0xFEF7 // Vehicle Electrical Power - VEP
+#define PGN_65276 0xFEFC // Dash Display - DD
+#define PGN_61444 0xF004 // Electronic Engine Controller 1 - EEC1
+#define PGN_60928 0xEE00 // Address Calimed - ACL
+#endif
+
+// door defines
+#define OPEN_DOOR_1 0x400000000000000
+#define OPEN_DOOR_2 0x1000000000000
+#define OPEN_DOOR_3 0x40000000000000
+#define OPEN_DOOR_4 0x100000000000
+#define OPEN_DOOR_5 0x400000000
+#define OPEN_DOOR_6 0x1000000
+
+// light defines
+#define HEAD_LIGHT 0x200000000000000
+#define PARK_LIGHT 0x100000000000000
+#define LIGHT_ERROR 0x400000000000000
+#define LEFT_TURN_SIGNAL 0x10000000000000
+#define RIGHT_TURN_SIGNAL 0x20000000000000
+#define HAZARD_SIGNAL 0x4000000000000
+
+#define LEFT_BLINK_ON 0x01
+#define RIGHT_BLINK_ON 0x02
+#define HAZARD_ON 0x4
+
+// Current gear defines
+#define GEAR_PARK 0xFB
+#define GEAR_REVERSE 0x7C
+#define GEAR_NEUTRAL 0x7D
+// #define GEAR_1 0x7E
+// #define GEAR_2 0x7F
+// #define GEAR_3 0x80
+// #define GEAR_4 0x81
+// #define GEAR_5 0x82
+// #define GEAR_6 0x83
+
+ClusterDataBackend::ClusterDataBackend(QObject* parent) :
+ QObject(parent),
+#ifndef CLUSTERDATA_SIMULATION
+ m_canDevice(Q_NULLPTR),
+#endif
+ m_vehicleSpeed(0.0),
+ m_latitude(52.53471566),
+ m_longitude(13.29339621),
+ m_direction(0.0),
+ m_flatTire(false),
+ m_lightFailure(false),
+ m_gear(1),
+ m_signalLights(0x0),
+ m_headLight(false),
+ m_parkLight(false),
+ m_carId(2),
+ m_brake(false),
+ m_engineTemp(60),
+ m_oilTemp(0.0),
+ m_oilPressure(0),
+ m_batteryPotential(80.0),
+ m_gasLevel(67.0),
+ m_rpm(4000)
+{
+
+ m_doorOpen.insert("frontLeft", false);
+ m_doorOpen.insert("frontRight", false);
+ m_doorOpen.insert("rearLeft", false);
+ m_doorOpen.insert("rearRight", false);
+ m_doorOpen.insert("trunk", false);
+ m_doorOpen.insert("hood", false);
+
+#ifndef CLUSTERDATA_SIMULATION
+ QCanBus* canBus(QCanBus::instance());
+ QList<QByteArray> plugins(canBus->plugins());
+ if (plugins.contains(SOCKETCAN)) {
+ m_canDevice = canBus->createDevice(SOCKETCAN, CANINTERFACE);
+ if (m_canDevice) {
+ connect(m_canDevice, SIGNAL(errorOccurred(QCanBusDevice::CanBusError)), this, SLOT(canError(QCanBusDevice::CanBusError)));
+ connect(m_canDevice, SIGNAL(framesReceived()), this, SLOT(canFramesReceived()));
+#ifdef DEBUG_CAN
+ connect(m_canDevice, SIGNAL(stateChanged(QCanBusDevice::CanBusDeviceState)), this, SLOT(canStateChanged(QCanBusDevice::CanBusDeviceState)));
+ qDebug() << "ClusterDataBackend::ClusterDataBackend - connectDevice:" <<
+#endif // DEBUG_CAN
+ m_canDevice->connectDevice();
+ }
+ }
+#endif // !CLUSTERDATA_SIMULATION
+}
+
+ClusterDataBackend::~ClusterDataBackend()
+{
+#ifndef CLUSTERDATA_SIMULATION
+ if (m_canDevice) {
+ m_canDevice->disconnectDevice();
+ }
+#else
+ if (m_tcpServerConnection)
+ m_tcpServerConnection->close();
+ m_tcpServer.close();
+#endif
+}
+
+QStringList ClusterDataBackend::availableZones() const
+{
+ return m_doorOpen.keys();
+}
+
+QMap<QString, QVariantMap> ClusterDataBackend::zoneMap() const
+{
+ return m_zonedFeatures;
+}
+
+void ClusterDataBackend::initializeAttributes()
+{
+ emit vehicleSpeedChanged(m_vehicleSpeed);
+ emit latitudeChanged(m_latitude);
+ emit longitudeChanged(m_longitude);
+ emit directionChanged(m_direction);
+ emit flatTireChanged(m_flatTire);
+ foreach (QString zone, m_doorOpen.keys()) {
+ emit doorOpenChanged(m_doorOpen.value(zone), zone);
+ }
+ emit lightFailureChanged(m_lightFailure);
+ emit reverseChanged(m_gear < 0);
+ emit leftTurnLightChanged(m_signalLights & LEFT_BLINK_ON);
+ emit rightTurnLightChanged(m_signalLights & RIGHT_BLINK_ON);
+ emit headLightChanged(m_headLight);
+ emit carIdChanged(m_carId);
+
+#ifdef CLUSTERDATA_SIMULATION
+ QHostAddress simuAddr("127.0.0.1");
+
+ QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
+ foreach (QNetworkInterface interface, interfaces) {
+ QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
+
+ foreach (QNetworkAddressEntry entry, addressEntries) {
+ if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
+ simuAddr = entry.ip();
+ }
+ }
+ }
+ if (m_tcpServer.listen(simuAddr, 32123)) {
+ connect(&m_tcpServer, SIGNAL(newConnection()),
+ this, SLOT(acceptConnection()));
+ qDebug() << "ClusterData server listening " << simuAddr << m_tcpServer.serverPort();
+ } else {
+ qWarning() << m_tcpServer.errorString();
+ }
+#endif
+}
+
+#ifdef CLUSTERDATA_SIMULATION
+void ClusterDataBackend::acceptConnection()
+{
+ m_tcpServerConnection = m_tcpServer.nextPendingConnection();
+ connect(m_tcpServerConnection, &QTcpSocket::readyRead,
+ this, &ClusterDataBackend::updateServerProgress);
+}
+
+void ClusterDataBackend::updateServerProgress()
+{
+ QString msg(m_tcpServerConnection->readAll());
+
+ foreach (QString msgAttr, msg.split(" ",QString::SkipEmptyParts)) {
+ QString attribute = msgAttr.section(':',0,0);
+ QString value = msgAttr.section(':',1,1);
+ if (attribute == "vehicleSpeed") {
+ emit vehicleSpeedChanged(value.toDouble());
+ } else if (attribute == "latitude") {
+ emit latitudeChanged(value.toDouble());
+ } else if (attribute == "longitude") {
+ emit longitudeChanged(value.toDouble());
+ } else if (attribute == "direction") {
+ emit directionChanged(value.toDouble());
+ } else if (attribute == "headLight") {
+ emit headLightChanged((bool)value.toInt());
+ } else if (attribute == "lightFailure") {
+ emit lightFailureChanged((bool)value.toInt());
+ } else if (attribute == "flatTire") {
+ emit flatTireChanged((bool)value.toInt());
+ } else if (attribute == "reverse") {
+ emit reverseChanged((bool)value.toInt());
+ } else if (attribute == "leftTurnLight") {
+ emit leftTurnLightChanged((bool)value.toInt());
+ } else if (attribute == "rightTurnLight") {
+ emit rightTurnLightChanged((bool)value.toInt());
+ } else if (attribute == "headLight") {
+ emit headLightChanged((bool)value.toInt());
+ } else if (attribute == "parkLight") {
+ emit parkLightChanged((bool)value.toInt());
+ } else if (attribute == "carId") {
+ emit carIdChanged(value.toInt());
+ } else if (attribute == "frontLeftDoorOpen") {
+ emit doorOpenChanged((bool)value.toInt(), "frontLeft");
+ } else if (attribute == "frontRightDoorOpen") {
+ emit doorOpenChanged((bool)value.toInt(), "frontRight");
+ } else if (attribute == "rearLeftDoorOpen") {
+ emit doorOpenChanged((bool)value.toInt(), "rearLeft");
+ } else if (attribute == "rearRightDoorOpen") {
+ emit doorOpenChanged((bool)value.toInt(), "rearRight");
+ } else if (attribute == "hoodOpen") {
+ emit doorOpenChanged((bool)value.toInt(), "hood");
+ } else if (attribute == "trunkOpen") {
+ emit doorOpenChanged((bool)value.toInt(), "trunk");
+ } else if (attribute == "hazardSignal") {
+ emit leftTurnLightChanged((bool)value.toInt());
+ emit rightTurnLightChanged((bool)value.toInt());
+ } else if (attribute == "brake") {
+ emit brakeChanged((bool)value.toInt());
+ } else if (attribute == "engineTemp") {
+ emit engineTempChanged(value.toInt());
+ } else if (attribute == "oilTemp") {
+ emit oilTempChanged(value.toDouble());
+ } else if (attribute == "oilPressure") {
+ emit oilPressureChanged(value.toInt());
+ } else if (attribute == "batteryPotential") {
+ emit batteryPotentialChanged(value.toDouble());
+ } else if (attribute == "gasLevel") {
+ emit gasLevelChanged(value.toDouble());
+ } else if (attribute == "rpm") {
+ emit rpmChanged(value.toInt());
+ } else if (attribute == "gear") {
+ emit gearChanged(value.toInt());
+ }
+ else {
+ qWarning() << "Unknown msg" << msg;
+ }
+ }
+}
+#else
+// Tire Condition - TIRE
+void ClusterDataBackend::handlePGN65268(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+// char tireId(data.at(0));
+// char pressure(data.at(1));
+// quint16 temperatureData(data.at(2) << 8);
+// temperatureData |= data.at(3);
+// double tireTemperature((0.03125 * (double)temperatureData) - 273);
+ m_flatTire = (data.at(4) & 0x30);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65268 - m_flatTire: %s", (m_flatTire ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit flatTireChanged(m_flatTire);
+ }
+}
+
+// Door Control 2 - DC2
+void ClusterDataBackend::handlePGN64933(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ quint64 doorData((quint64)data.at(0) << 56);
+ doorData |= ((quint64)data.at(1) << 48);
+ doorData |= ((quint64)data.at(2) << 40);
+ doorData |= ((quint64)data.at(3) << 32);
+ doorData |= ((quint64)data.at(4) << 24);
+ doorData |= ((quint64)data.at(5) << 16);
+ doorData |= ((quint64)data.at(6) << 8);
+ doorData |= (quint64)data.at(7);
+
+ bool frontLeft(doorData & OPEN_DOOR_1);
+ bool frontRight(doorData & OPEN_DOOR_2);
+ bool rearLeft(doorData & OPEN_DOOR_3);
+ bool rearRight(doorData & OPEN_DOOR_4);
+ bool trunk(doorData & OPEN_DOOR_5);
+ bool hood(doorData & OPEN_DOOR_6);
+
+ if (m_doorOpen.value("frontLeft") != frontLeft) {
+ m_doorOpen.insert("frontLeft", frontLeft);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, frontLeft: %s", (frontLeft ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit doorOpenChanged(frontLeft, "frontLeft");
+ }
+ if (m_doorOpen.value("frontRight") != frontRight) {
+ m_doorOpen.insert("frontRight", frontRight);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, frontRight: %s", (frontRight ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit doorOpenChanged(frontRight, "frontRight");
+ }
+ if (m_doorOpen.value("rearLeft") != rearLeft) {
+ m_doorOpen.insert("rearLeft", rearLeft);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, rearLeft: %s", (rearLeft ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit doorOpenChanged(rearLeft, "rearLeft");
+ }
+ if (m_doorOpen.value("rearRight") != rearRight) {
+ m_doorOpen.insert("rearRight", rearRight);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, rearRight: %s", (rearRight ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit doorOpenChanged(rearRight, "rearRight");
+ }
+ if (m_doorOpen.value("trunk") != trunk) {
+ m_doorOpen.insert("trunk", trunk);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, trunk: %s", (trunk ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit doorOpenChanged(trunk, "trunk");
+ }
+ if (m_doorOpen.value("hood") != hood) {
+ m_doorOpen.insert("hood", hood);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, hood: %s", (hood ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit doorOpenChanged(hood, "hood");
+ }
+ }
+}
+
+// Light Control
+void ClusterDataBackend::handlePGN64972(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ quint64 lightData((quint64)data.at(0) << 56);
+ lightData |= ((quint64)data.at(1) << 48);
+ lightData |= ((quint64)data.at(2) << 40);
+ lightData |= ((quint64)data.at(3) << 32);
+ lightData |= ((quint64)data.at(4) << 24);
+ lightData |= ((quint64)data.at(5) << 16);
+ lightData |= ((quint64)data.at(6) << 8);
+ lightData |= data.at(7);
+
+ if (m_headLight != (lightData & HEAD_LIGHT)) {
+ m_headLight = (lightData & HEAD_LIGHT);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - m_headLight: %s", (m_headLight ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit headLightChanged(m_headLight);
+ }
+ if (m_parkLight != (lightData & PARK_LIGHT)) {
+ m_parkLight = (lightData & PARK_LIGHT);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - m_parkLight: %s", (m_parkLight ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit parkLightChanged(m_parkLight);
+ }
+ if (m_lightFailure != (lightData & LIGHT_ERROR)) {
+ m_lightFailure = (lightData & LIGHT_ERROR);
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - m_lightFailure: %s", (m_lightFailure ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit lightFailureChanged(m_lightFailure);
+ }
+ if ((bool)(m_signalLights & LEFT_BLINK_ON) != (bool)(lightData & LEFT_TURN_SIGNAL)) {
+ if (lightData & LEFT_TURN_SIGNAL) {
+ m_signalLights |= LEFT_BLINK_ON;
+ }
+ else {
+ m_signalLights &= ~LEFT_BLINK_ON;
+ }
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - leftTurnLight: %s", ((lightData & LEFT_TURN_SIGNAL) ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit leftTurnLightChanged(lightData & LEFT_TURN_SIGNAL);
+ }
+ if ((bool)(m_signalLights & RIGHT_BLINK_ON) != (bool)(lightData & RIGHT_TURN_SIGNAL)) {
+ if (lightData & RIGHT_TURN_SIGNAL) {
+ m_signalLights |= RIGHT_BLINK_ON;
+ }
+ else {
+ m_signalLights &= ~RIGHT_BLINK_ON;
+ }
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - rightTurnLight: %s", ((lightData & RIGHT_TURN_SIGNAL) ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit rightTurnLightChanged(lightData & RIGHT_TURN_SIGNAL);
+ }
+ if ((bool)(m_signalLights & HAZARD_ON) != (bool)(lightData & HAZARD_SIGNAL)) {
+ if (lightData & HAZARD_SIGNAL) {
+ m_signalLights |= HAZARD_ON;
+ if (!(m_signalLights & LEFT_BLINK_ON)) {
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - hazard ON, leftTurnLight: true");
+#endif // DEBUG_CAN
+ emit leftTurnLightChanged(true);
+ }
+ if (!(m_signalLights & RIGHT_BLINK_ON)) {
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - hazard ON, rightTurnLight: true");
+#endif // DEBUG_CAN
+ emit rightTurnLightChanged(true);
+ }
+ }
+ else {
+ m_signalLights &= ~HAZARD_ON;
+ if (!(m_signalLights & LEFT_BLINK_ON)) {
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - hazard OFF, leftTurnLight: false");
+#endif // DEBUG_CAN
+ emit leftTurnLightChanged(false);
+ }
+ if (!(m_signalLights & RIGHT_BLINK_ON)) {
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN64972 - hazard OFF, rightTurnLight: false");
+#endif // DEBUG_CAN
+ emit rightTurnLightChanged(false);
+ }
+ }
+ }
+ }
+}
+
+// Electronic Transmission Controller 2 - ETC2
+void ClusterDataBackend::handlePGN61445(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ char gear(data.at(3));
+ if (gear == (char)GEAR_PARK) {
+ m_gear = 0xff;
+ }
+ else if (m_gear == -1 && gear != (char)GEAR_REVERSE) {
+ m_gear = (gear - GEAR_NEUTRAL);
+ emit reverseChanged(false);
+ }
+ else if (m_gear != -1 && gear == (char)GEAR_REVERSE) {
+ m_gear = -1;
+ emit reverseChanged(true);
+ }
+ else {
+ m_gear = (gear - GEAR_NEUTRAL);
+ }
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN61445 - gear: %d", m_gear);
+#endif // DEBUG_CAN
+ emit gearChanged(m_gear);
+ }
+}
+
+// Cruise Control/Vehicle Speed - CCVS
+void ClusterDataBackend::handlePGN65265(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ qint16 speed((data.at(1) << 8));
+ speed |= data.at(2);
+ double vehicleSpeed(0.00390625 * (double)speed);
+
+ if (m_vehicleSpeed != vehicleSpeed) {
+ m_vehicleSpeed = vehicleSpeed;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65265 - vehicle speed: %f", m_vehicleSpeed);
+#endif // DEBUG_CAN
+ emit vehicleSpeedChanged(m_vehicleSpeed);
+ }
+
+ bool brakeOn(data.at(3) & 0x10);
+ if (m_brake != brakeOn) {
+ m_brake = brakeOn;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65265 - m_brake: %s", (m_brake ? "true" : "false"));
+#endif // DEBUG_CAN
+ emit brakeChanged(m_brake);
+ }
+ }
+}
+
+// vehicle position - VP
+void ClusterDataBackend::handlePGN65267(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+
+ if (data.size() == 8) {
+ quint32 lat((data.at(0) << 24));
+ lat |= ((data.at(1) << 16));
+ lat |= ((data.at(2) << 8));
+ lat |= data.at(3);
+
+ quint32 lon(data.at(4) << 24);
+ lon |= (data.at(5) << 16);
+ lon |= (data.at(6) << 8);
+ lon |= data.at(7);
+
+ double latitude((((double)lat) * 1e-7) - 210);
+ double longitude((((double)lon) * 1e-7) - 210);
+
+ bool positionChanged(false);
+ if (m_latitude != latitude) {
+ m_latitude = latitude;
+ positionChanged = true;
+ }
+ if (m_longitude != longitude) {
+ m_longitude = longitude;
+ positionChanged = true;
+ }
+ if (positionChanged) {
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN129025 - lat: %f, lon: %f", m_latitude, m_longitude);
+#endif // DEBUG_CAN
+ emit latitudeChanged(m_latitude);
+ emit longitudeChanged(m_longitude);
+ }
+ }
+}
+
+// vehicle direction/speed
+void ClusterDataBackend::handlePGN65256(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ quint16 directionData((data.at(0) << 8));
+ directionData |= data.at(1);
+ double direction(0.0078125 * (double)directionData); // 1/128 deg/bit
+
+ if (m_direction != direction) {
+ m_direction = direction;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65256 - m_direction: %f", m_direction);
+#endif // DEBUG_CAN
+ emit directionChanged(m_direction);
+ }
+ }
+}
+
+// Engine Temperature 1 - ET1
+void ClusterDataBackend::handlePGN65262(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ qint8 engineTemp(data.at(0) - 40);
+ if (m_engineTemp != engineTemp) {
+ m_engineTemp = engineTemp;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65262 - m_engineTemp: %d", m_engineTemp);
+#endif // DEBUG_CAN
+ emit engineTempChanged(m_engineTemp);
+ }
+ quint16 oilTempData(data.at(2) << 8);
+ oilTempData |= data.at(3);
+ double oilTemp(0.03125 * ((double)oilTempData) - 273.0);
+ if (m_oilTemp != oilTemp) {
+ m_oilTemp = oilTemp;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65262 - m_oilTemp: %f", m_oilTemp);
+#endif // DEBUG_CAN
+ emit oilTempChanged(m_oilTemp);
+ }
+ }
+}
+
+// Engine Fluid Level/Pressure 1 - EFL/P1
+void ClusterDataBackend::handlePGN65263(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ int oilPressure(4 * data.at(3));
+ if (m_oilPressure != oilPressure) {
+ m_oilPressure = oilPressure;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65263 - m_oilPressure: %d", m_oilPressure);
+#endif // DEBUG_CAN
+ emit oilPressureChanged(m_oilPressure);
+ }
+ }
+}
+
+// Vehicle Electrical Power - VEP
+void ClusterDataBackend::handlePGN65271(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ quint16 batteryPotentialData(data.at(6) << 8);
+ batteryPotentialData |= data.at(7);
+ double batteryPotential(0.05 * (double)batteryPotentialData);
+ if (m_batteryPotential != batteryPotential) {
+ m_batteryPotential = batteryPotential;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65271 - m_batteryPotential: %f", m_batteryPotential);
+#endif // DEBUG_CAN
+ emit batteryPotentialChanged(m_batteryPotential);
+ }
+ }
+}
+
+// Dash Display - DD
+void ClusterDataBackend::handlePGN65276(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ double gasLevel(0.4 * (double)data.at(1));
+ if (m_gasLevel != gasLevel) {
+ m_gasLevel = gasLevel;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN65276 - m_gasLevel: %f", m_gasLevel);
+#endif // DEBUG_CAN
+ emit gasLevelChanged(m_gasLevel);
+ }
+ }
+}
+
+// Electronic Engine Controller 1 - EEC1
+void ClusterDataBackend::handlePGN61444(const QCanBusFrame& frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ quint16 rpmData(data.at(3) << 8);
+ rpmData |= data.at(4);
+ int rpm(0.125 * (double)rpmData);
+ if (m_rpm != rpm) {
+ m_rpm = rpm;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN61444 - m_rpm: %d", m_rpm);
+#endif // DEBUG_CAN
+ emit rpmChanged(m_rpm);
+ }
+ }
+}
+
+// Address Claimed - ACL
+void ClusterDataBackend::handlePGN60928(const QCanBusFrame &frame)
+{
+ QByteArray data(frame.payload());
+ if (data.size() == 8) {
+ // only 21 bits allowed (0x0 - 0x1FFFFF), pos 1.1 - 3.5 in message
+ quint16 carIdData((data.at(0) & 0xff) << 13);
+ carIdData |= ((data.at(1) & 0xff) << 5);
+ carIdData |= ((data.at(2) & 0xf8) >> 3);
+ if (m_carId != (int)carIdData) {
+ m_carId = carIdData;
+#ifdef DEBUG_CAN
+ qDebug("ClusterDataBackend::handlePGN60928 - carId: %d", m_carId);
+#endif // DEBUG_CAN
+ emit carIdChanged(m_carId);
+ }
+ }
+}
+
+void ClusterDataBackend::canError(QCanBusDevice::CanBusError error)
+{
+ qWarning("ClusterDataBackend::canError - code: %d, error: %s", (int)error, qPrintable(m_canDevice->errorString()));
+ m_canDevice->disconnectDevice();
+}
+
+void ClusterDataBackend::canFramesReceived()
+{
+ while (m_canDevice && m_canDevice->framesAvailable() > 0) {
+ QCanBusFrame frame(m_canDevice->readFrame());
+
+ quint32 frameId(frame.frameId());
+
+ switch (frameId) {
+ case PGN_65268 : handlePGN65268(frame); break; // Tire Condition - TIRE
+ case PGN_64933 : handlePGN64933(frame); break; // Door Control 2 - DC2
+ case PGN_64972 : handlePGN64972(frame); break; // Light Control
+ case PGN_61445 : handlePGN61445(frame); break; // Electronic Transmission Controller 2 - ETC2
+ case PGN_65265 : handlePGN65265(frame); break; // Cruise Control/Vehicle Speed - CCVS
+ case PGN_65267 : handlePGN65267(frame); break; // vehicle position - VP
+ case PGN_65256 : handlePGN65256(frame); break; // vehicle direction/speed
+ case PGN_65262 : handlePGN65262(frame); break; // Engine Temperature 1 - ET1
+ case PGN_65263 : handlePGN65263(frame); break; // Engine Fluid Level/Pressure 1 - EFL/P1
+ case PGN_65271 : handlePGN65271(frame); break; // Vehicle Electrical Power - VEP
+ case PGN_65276 : handlePGN65276(frame); break; // Dash Display - DD
+ case PGN_61444 : handlePGN61444(frame); break; // Electronic Engine Controller 1 - EEC1
+ case PGN_60928 : handlePGN60928(frame); break; // Address Claimed - ACL
+ default: qWarning("canFramesReceived - unknown frame id: %d", frameId);
+ }
+#ifdef DEBUG_CAN
+ QByteArray data(frame.payload());
+ const char* constData(data.constData());
+ int payLoadSize(data.size());
+ QString dataString;
+ for (int i(0); i < payLoadSize; i++) {
+ if (!dataString.isEmpty()) dataString.append(".");
+ dataString.append(QString::fromLatin1("%1").arg((int)constData[i], 2, 16, QChar('0')));
+ }
+ qDebug() << "ClusterDataBackend::canFramesReceived - id:" << frameId << "- data:" << dataString.toLatin1().constData();
+#endif // DEBUG_CAN
+ }
+}
+
+void ClusterDataBackend::canStateChanged(QCanBusDevice::CanBusDeviceState state)
+{
+#ifdef DEBUG_CAN
+ qDebug() << "ClusterDataBackend::canStateChanged - state:" << state;
+#else
+ Q_UNUSED(state)
+#endif // DEBUG_CAN
+}
+#endif
diff --git a/CenterConsole/plugins/clusterdatasource/clusterdatabackend.h b/CenterConsole/plugins/clusterdatasource/clusterdatabackend.h
new file mode 100644
index 0000000..944aacd
--- /dev/null
+++ b/CenterConsole/plugins/clusterdatasource/clusterdatabackend.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Pelagicore AG
+** Contact: http://www.qt.io/ or http://www.pelagicore.com/
+**
+** This file is part of the QtIVI module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3-PELAGICORE$
+** Commercial License Usage
+** Licensees holding valid commercial Qt IVI licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Pelagicore. For licensing terms
+** and conditions, contact us at http://www.pelagicore.com.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#ifndef CLUSTERDATABACKEND_H
+#define CLUSTERDATABACKEND_H
+
+#include <QObject>
+#include <QMap>
+#include <QVariant>
+
+#ifndef CLUSTERDATA_SIMULATION
+#include <QCanBusDevice>
+#include <QCanBusFrame>
+#else
+#include <QTcpServer>
+#include <QTcpSocket>
+class QTimer;
+#endif
+
+class ClusterDataBackend : public QObject
+{
+ Q_OBJECT
+
+public:
+ ClusterDataBackend(QObject* parent=0);
+ ~ClusterDataBackend();
+
+public:
+ QStringList availableZones() const;
+ QMap<QString, QVariantMap> zoneMap() const;
+ void initializeAttributes();
+
+signals:
+ void vehicleSpeedChanged(double vehicleSpeed, const QString &zone = QString());
+ void latitudeChanged(double latitude, const QString &zone = QString());
+ void longitudeChanged(double longitude, const QString &zone = QString());
+ void directionChanged(double direction, const QString &zone = QString());
+ void flatTireChanged(bool flatTire, const QString &zone = QString());
+ void doorOpenChanged(bool doorOpen, const QString &zone = QString());
+ void lightFailureChanged(bool lightFailure, const QString &zone = QString());
+ void reverseChanged(bool Reverse, const QString &zone = QString());
+ void leftTurnLightChanged(bool leftTurnLight, const QString &zone = QString());
+ void rightTurnLightChanged(bool rightTurnLight, const QString &zone = QString());
+ void headLightChanged(bool headLight, const QString &zone = QString());
+ void parkLightChanged(bool parkLight, const QString &zone = QString());
+ void carIdChanged(int carId, const QString &zone = QString());
+ void brakeChanged(bool brakeOn, const QString &zone = QString());
+ void engineTempChanged(int engineTemp, const QString &zone = QString());
+ void oilTempChanged(double oilTemp, const QString &zone = QString());
+ void oilPressureChanged(int oilPressure, const QString &zone = QString());
+ void batteryPotentialChanged(double batteryPotential, const QString &zone = QString());
+ void gasLevelChanged(double gasLevel, const QString &zone = QString());
+ void rpmChanged(int rpm, const QString &zone = QString());
+ void gearChanged(int gear, const QString &zone = QString());
+
+private:
+#ifndef CLUSTERDATA_SIMULATION
+ void handlePGN65268(const QCanBusFrame& frame); // Tire Condition - TIRE
+ void handlePGN64933(const QCanBusFrame& frame); // Door Control 2 - DC2
+ void handlePGN64972(const QCanBusFrame& frame); // Light Control
+ void handlePGN61445(const QCanBusFrame& frame); // Electronic Transmission Controller 2 - ETC2
+ void handlePGN65265(const QCanBusFrame& frame); // Cruise Control/Vehicle Speed - CCVS
+ void handlePGN65267(const QCanBusFrame& frame); // vehicle position - VP
+ void handlePGN65256(const QCanBusFrame& frame); // vehicle direction/speed
+ void handlePGN65262(const QCanBusFrame& frame); // Engine Temperature 1 - ET1
+ void handlePGN65263(const QCanBusFrame& frame); // Engine Fluid Level/Pressure 1 - EFL/P1
+ void handlePGN65271(const QCanBusFrame& frame); // Vehicle Electrical Power - VEP
+ void handlePGN65276(const QCanBusFrame& frame); // Dash Display - DD
+ void handlePGN61444(const QCanBusFrame& frame); // Electronic Engine Controller 1 - EEC1
+ void handlePGN60928(const QCanBusFrame& frame); // Address Claimed - ACL
+
+private slots:
+ void canError(QCanBusDevice::CanBusError error);
+ void canFramesReceived();
+ void canStateChanged(QCanBusDevice::CanBusDeviceState state);
+#else
+public slots:
+ void acceptConnection();
+private slots:
+ void updateServerProgress();
+#endif
+
+private:
+#ifndef CLUSTERDATA_SIMULATION
+ QCanBusDevice* m_canDevice;
+#else
+ QTcpServer m_tcpServer;
+ QTcpSocket *m_tcpServerConnection;
+#endif
+ double m_vehicleSpeed;
+ double m_latitude;
+ double m_longitude;
+ double m_direction;
+ bool m_flatTire;
+ QMap<QString,bool> m_doorOpen;
+ QMap<QString, QVariantMap> m_zonedFeatures;
+ bool m_lightFailure;
+ int m_gear;
+ char m_signalLights;
+ bool m_headLight;
+ bool m_parkLight;
+ int m_carId;
+ bool m_brake;
+ qint8 m_engineTemp;
+ double m_oilTemp;
+ int m_oilPressure;
+ double m_batteryPotential;
+ double m_gasLevel;
+ int m_rpm;
+
+};
+
+#endif // CLUSTERDATABACKEND_H
diff --git a/CenterConsole/plugins/clusterdatasource/clusterdatasource.pro b/CenterConsole/plugins/clusterdatasource/clusterdatasource.pro
new file mode 100644
index 0000000..513b9d8
--- /dev/null
+++ b/CenterConsole/plugins/clusterdatasource/clusterdatasource.pro
@@ -0,0 +1,31 @@
+include (../../../deployment.pri)
+TEMPLATE = lib
+TARGET = clusterdatasourceplugin
+QT += qml quick
+CONFIG += qt plugin c++11
+
+TARGET = clusterdatasourceplugin
+uri = com.qtcompany.clusterdemodata
+
+SOURCES += \
+ plugin.cpp \
+ qtiviclusterdata.cpp \
+ clusterdatabackend.cpp
+
+HEADERS += \
+ qtiviclusterdata.h \
+ clusterdatabackend.h
+
+#qtHaveModule(serialbus):!simulation_only {
+#QT += serialbus
+#} else: {
+DEFINES += CLUSTERDATA_SIMULATION
+#}
+
+OTHER_FILES = qmldir
+
+qmldir.files = qmldir
+
+qmldir.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+target.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+INSTALLS += target qmldir
diff --git a/CenterConsole/plugins/clusterdatasource/plugin.cpp b/CenterConsole/plugins/clusterdatasource/plugin.cpp
new file mode 100644
index 0000000..83b7fd2
--- /dev/null
+++ b/CenterConsole/plugins/clusterdatasource/plugin.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include <QtQml/qqmlextensionplugin.h>
+#include <qqml.h>
+#include "qtiviclusterdata.h"
+
+static QObject *clusterDataSingletonFactory(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(scriptEngine)
+ Q_UNUSED(engine)
+
+ return new QtIVIClusterData();
+}
+
+class HoundPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("com.qtcompany.clusterdemodata"));
+ Q_UNUSED(uri);
+ qmlRegisterType<QtIVIClusterData>(uri, 1, 0, "ClusterData");
+ }
+};
+
+#include "plugin.moc"
diff --git a/CenterConsole/plugins/clusterdatasource/qmldir b/CenterConsole/plugins/clusterdatasource/qmldir
new file mode 100644
index 0000000..d53a57e
--- /dev/null
+++ b/CenterConsole/plugins/clusterdatasource/qmldir
@@ -0,0 +1,2 @@
+module com.qtcompany.clusterdemodata
+plugin clusterdatasourceplugin
diff --git a/CenterConsole/plugins/clusterdatasource/qtiviclusterdata.cpp b/CenterConsole/plugins/clusterdatasource/qtiviclusterdata.cpp
new file mode 100644
index 0000000..d3d4339
--- /dev/null
+++ b/CenterConsole/plugins/clusterdatasource/qtiviclusterdata.cpp
@@ -0,0 +1,388 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "qtiviclusterdata.h"
+
+QtIVIClusterData::QtIVIClusterData(QObject *parent)
+ : QObject(parent),
+ backend(new ClusterDataBackend),
+ m_vehicleSpeed(0),
+ m_latitude(0),
+ m_longitude(0),
+ m_direction(0),
+ m_flatTire(false),
+ m_doorOpen(false),
+ m_lightFailure(false),
+ m_reverse(false),
+ m_leftTurnLight(false),
+ m_rightTurnLight(false),
+ m_headLight(false),
+ m_parkLight(false),
+ m_carId(2),
+ m_brake(false),
+ m_engineTemp(60),
+ m_oilTemp(0.0),
+ m_oilPressure(0),
+ m_batteryPotential(80.0),
+ m_gasLevel(67.0),
+ m_rpm(4000),
+ m_gear(1)
+{
+ connectToServiceObject();
+}
+
+
+void QtIVIClusterData::connectToServiceObject()
+{
+ if (!backend)
+ return;
+ connect(backend, &ClusterDataBackend::vehicleSpeedChanged,
+ this, &QtIVIClusterData::onVehicleSpeedChanged);
+ connect(backend, &ClusterDataBackend::latitudeChanged,
+ this, &QtIVIClusterData::onLatitudeChanged);
+ connect(backend, &ClusterDataBackend::longitudeChanged,
+ this, &QtIVIClusterData::onLongitudeChanged);
+ connect(backend, &ClusterDataBackend::directionChanged,
+ this, &QtIVIClusterData::onDirectionChanged);
+ connect(backend, &ClusterDataBackend::flatTireChanged,
+ this, &QtIVIClusterData::onFlatTireChanged);
+ connect(backend, &ClusterDataBackend::doorOpenChanged,
+ this, &QtIVIClusterData::onDoorOpenChanged);
+ connect(backend, &ClusterDataBackend::lightFailureChanged,
+ this, &QtIVIClusterData::onLightFailureChanged);
+ connect(backend, &ClusterDataBackend::reverseChanged,
+ this, &QtIVIClusterData::onReverseChanged);
+ connect(backend, &ClusterDataBackend::leftTurnLightChanged,
+ this, &QtIVIClusterData::onLeftTurnLightChanged);
+ connect(backend, &ClusterDataBackend::rightTurnLightChanged,
+ this, &QtIVIClusterData::onRightTurnLightChanged);
+ connect(backend, &ClusterDataBackend::headLightChanged,
+ this, &QtIVIClusterData::onHeadLightChanged);
+ connect(backend, &ClusterDataBackend::carIdChanged,
+ this, &QtIVIClusterData::onCarIdChanged);
+ connect(backend, &ClusterDataBackend::brakeChanged,
+ this, &QtIVIClusterData::onBrakeChanged);
+ connect(backend, &ClusterDataBackend::engineTempChanged,
+ this, &QtIVIClusterData::onEngineTempChanged);
+ connect(backend, &ClusterDataBackend::oilTempChanged,
+ this, &QtIVIClusterData::onOilTempChanged);
+ connect(backend, &ClusterDataBackend::oilPressureChanged,
+ this, &QtIVIClusterData::onOilPressureChanged);
+ connect(backend, &ClusterDataBackend::batteryPotentialChanged,
+ this, &QtIVIClusterData::onBatteryPotentialChanged);
+ connect(backend, &ClusterDataBackend::gasLevelChanged,
+ this, &QtIVIClusterData::onGasLevelChanged);
+ connect(backend, &ClusterDataBackend::rpmChanged,
+ this, &QtIVIClusterData::onRpmChanged);
+ connect(backend, &ClusterDataBackend::gearChanged,
+ this, &QtIVIClusterData::onGearChanged);
+ connect(backend, &ClusterDataBackend::parkLightChanged,
+ this, &QtIVIClusterData::onParkLightChanged);
+ backend->initializeAttributes();
+ initializeZones();
+}
+ZonedProperties *QtIVIClusterData::zoneAt(const QString &zone) const
+{
+ foreach (ZonedProperties *f, m_zoneFeatures)
+ if (f->zone() == zone)
+ return f;
+ return 0;
+}
+void QtIVIClusterData::initializeZones()
+{
+ foreach (const QString &zone, backend->availableZones()) {
+ ZonedProperties* f = zoneAt(zone);
+ if (!f) {
+ f = new ZonedProperties;
+ f->setZone(zone);
+ }
+ if (f) {
+ m_zoneFeatures.append(f);
+ m_zoneFeatureList.append(QVariant::fromValue(f));
+ m_zoneFeatureMap.insert(f->zone(), QVariant::fromValue(f));
+ emit zonesChanged();
+ }
+ }
+}
+QVariantMap QtIVIClusterData::zoneFeatureMap() const
+{
+ return m_zoneFeatureMap;
+
+}
+double QtIVIClusterData::vehicleSpeed() const
+{
+ return m_vehicleSpeed;
+}
+double QtIVIClusterData::latitude() const
+{
+ return m_latitude;
+}
+double QtIVIClusterData::longitude() const
+{
+ return m_longitude;
+}
+double QtIVIClusterData::direction() const
+{
+ return m_direction;
+}
+bool QtIVIClusterData::flatTire() const
+{
+ return m_flatTire;
+}
+bool QtIVIClusterData::doorOpen() const
+{
+ return m_doorOpen;
+}
+bool QtIVIClusterData::lightFailure() const
+{
+ return m_lightFailure;
+}
+bool QtIVIClusterData::reverse() const
+{
+ return m_reverse;
+}
+
+bool QtIVIClusterData::leftTurnLight() const
+{
+ return m_leftTurnLight;
+}
+
+bool QtIVIClusterData::rightTurnLight() const
+{
+ return m_rightTurnLight;
+}
+
+bool QtIVIClusterData::headLight() const
+{
+ return m_headLight;
+}
+
+bool QtIVIClusterData::parkLight() const
+{
+ return m_parkLight;
+}
+
+int QtIVIClusterData::carId() const
+{
+ return m_carId;
+}
+
+bool QtIVIClusterData::brake() const
+{
+ return m_brake;
+}
+
+int QtIVIClusterData::engineTemp() const
+{
+ return m_engineTemp;
+}
+
+double QtIVIClusterData::oilTemp() const
+{
+ return m_oilTemp;
+}
+
+int QtIVIClusterData::oilPressure() const
+{
+ return m_oilPressure;
+}
+
+double QtIVIClusterData::batteryPotential() const
+{
+ return m_batteryPotential;
+}
+
+double QtIVIClusterData::gasLevel() const
+{
+ return m_gasLevel;
+}
+
+int QtIVIClusterData::rpm() const
+{
+ return m_rpm;
+}
+
+int QtIVIClusterData::gear() const
+{
+ return m_gear;
+}
+void QtIVIClusterData::classBegin()
+{
+}
+void QtIVIClusterData::componentComplete()
+{
+}
+void QtIVIClusterData::onVehicleSpeedChanged(double vehicleSpeed, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_vehicleSpeed = vehicleSpeed;
+ emit vehicleSpeedChanged(vehicleSpeed);
+}
+
+void QtIVIClusterData::onLatitudeChanged(double latitude, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_latitude = latitude;
+ emit latitudeChanged(latitude);
+}
+
+void QtIVIClusterData::onLongitudeChanged(double longitude, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_longitude = longitude;
+ emit longitudeChanged(longitude);
+}
+
+void QtIVIClusterData::onDirectionChanged(double direction, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_direction = direction;
+ emit directionChanged(direction);
+}
+
+void QtIVIClusterData::onFlatTireChanged(bool flatTire, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_flatTire = flatTire;
+ emit flatTireChanged(flatTire);
+}
+
+void QtIVIClusterData::onDoorOpenChanged(bool doorOpen, const QString &zone)
+{
+ ZonedProperties *z = zoneAt(zone);
+ if (z) {
+ z->setDoorOpen(doorOpen);
+ }
+}
+
+void QtIVIClusterData::onLightFailureChanged(bool lightFailure, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_lightFailure = lightFailure;
+ emit lightFailureChanged(lightFailure);
+}
+
+void QtIVIClusterData::onReverseChanged(bool reverse, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_reverse = reverse;
+ emit reverseChanged(reverse);
+}
+
+void QtIVIClusterData::onLeftTurnLightChanged(bool leftTurnLight, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_leftTurnLight = leftTurnLight;
+ emit leftTurnLightChanged(leftTurnLight);
+}
+
+void QtIVIClusterData::onRightTurnLightChanged(bool rightTurnLight, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_rightTurnLight = rightTurnLight;
+ emit rightTurnLightChanged(rightTurnLight);
+}
+
+void QtIVIClusterData::onHeadLightChanged(bool headLight, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_headLight = headLight;
+ emit headLightChanged(headLight);
+}
+
+void QtIVIClusterData::onParkLightChanged(bool parkLight, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_parkLight = parkLight;
+ emit parkLightChanged(parkLight);
+}
+
+void QtIVIClusterData::onCarIdChanged(int carId, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_carId = carId;
+ emit carIdChanged(carId);
+}
+
+void QtIVIClusterData::onBrakeChanged(bool brakeOn, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_brake = brakeOn;
+ emit brakeChanged(brakeOn);
+}
+
+void QtIVIClusterData::onEngineTempChanged(int engineTemp, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_engineTemp = engineTemp;
+ emit engineTempChanged(engineTemp);
+}
+
+void QtIVIClusterData::onOilTempChanged(double oilTemp, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_oilTemp = oilTemp;
+ emit oilTempChanged(oilTemp);
+}
+
+void QtIVIClusterData::onOilPressureChanged(int oilPressure, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_oilPressure = oilPressure;
+ emit oilPressureChanged(oilPressure);
+}
+
+void QtIVIClusterData::onBatteryPotentialChanged(double batteryPotential, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_batteryPotential = batteryPotential;
+ emit batteryPotentialChanged(batteryPotential);
+}
+
+void QtIVIClusterData::onGasLevelChanged(double gasLevel, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_gasLevel = gasLevel;
+ emit gasLevelChanged(gasLevel);
+}
+
+void QtIVIClusterData::onRpmChanged(int rpm, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_rpm = rpm;
+ emit rpmChanged(rpm);
+}
+
+void QtIVIClusterData::onGearChanged(int gear, const QString &zone)
+{
+ Q_UNUSED(zone);
+ m_gear = gear;
+ emit gearChanged(gear);
+}
diff --git a/CenterConsole/plugins/clusterdatasource/qtiviclusterdata.h b/CenterConsole/plugins/clusterdatasource/qtiviclusterdata.h
new file mode 100644
index 0000000..4318eef
--- /dev/null
+++ b/CenterConsole/plugins/clusterdatasource/qtiviclusterdata.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef CLUSTERDATA_H
+#define CLUSTERDATA_H
+
+#include <QObject>
+#include <QQmlParserStatus>
+#include <QQmlProperty>
+#include "clusterdatabackend.h"
+
+class ClusterDataBackend;
+class ZonedProperties : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool doorOpen READ doorOpen NOTIFY doorOpenChanged)
+public:
+ ZonedProperties(QObject *parent=0) : QObject(parent), m_zone(""), m_doorOpen(false) {}
+ void setZone(const QString &zone) { m_zone = zone; }
+ QString zone() { return m_zone; }
+ bool doorOpen() { return m_doorOpen; }
+ void setDoorOpen(const bool &d) { m_doorOpen = d; emit doorOpenChanged(); }
+signals:
+ void zoneChanged(const QString &zone);
+ void doorOpenChanged();
+private:
+ QString m_zone;
+ bool m_doorOpen;
+};
+class QtIVIClusterData : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+
+ Q_PROPERTY(double vehicleSpeed READ vehicleSpeed NOTIFY vehicleSpeedChanged)
+ Q_PROPERTY(double latitude READ latitude NOTIFY latitudeChanged)
+ Q_PROPERTY(double longitude READ longitude NOTIFY longitudeChanged)
+ Q_PROPERTY(double direction READ direction NOTIFY directionChanged)
+ Q_PROPERTY(bool flatTire READ flatTire NOTIFY flatTireChanged)
+ Q_PROPERTY(bool lightFailure READ lightFailure NOTIFY lightFailureChanged)
+ Q_PROPERTY(bool reverse READ reverse NOTIFY reverseChanged)
+ Q_PROPERTY(bool leftTurnLight READ leftTurnLight NOTIFY leftTurnLightChanged)
+ Q_PROPERTY(bool rightTurnLight READ rightTurnLight NOTIFY rightTurnLightChanged)
+ Q_PROPERTY(bool headLight READ headLight NOTIFY headLightChanged)
+ Q_PROPERTY(bool parkLight READ parkLight NOTIFY parkLightChanged)
+ Q_PROPERTY(int carId READ carId NOTIFY carIdChanged)
+ Q_PROPERTY(bool brake READ brake NOTIFY brakeChanged)
+ Q_PROPERTY(int engineTemp READ engineTemp NOTIFY engineTempChanged)
+ Q_PROPERTY(double oilTemp READ oilTemp NOTIFY oilTempChanged)
+ Q_PROPERTY(int oilPressure READ oilPressure NOTIFY oilPressureChanged)
+ Q_PROPERTY(double batteryPotential READ batteryPotential NOTIFY batteryPotentialChanged)
+ Q_PROPERTY(double gasLevel READ gasLevel NOTIFY gasLevelChanged)
+ Q_PROPERTY(int rpm READ rpm NOTIFY rpmChanged)
+ Q_PROPERTY(int gear READ gear NOTIFY gearChanged)
+ Q_PROPERTY(QVariantMap zoneAt READ zoneFeatureMap NOTIFY zonesChanged)
+public:
+ explicit QtIVIClusterData(QObject *parent = 0);
+
+ double vehicleSpeed() const;
+ double latitude() const;
+ double longitude() const;
+ double direction() const;
+ bool flatTire() const;
+ bool doorOpen() const;
+ bool lightFailure() const;
+ bool reverse() const;
+ bool leftTurnLight() const;
+ bool rightTurnLight() const;
+ bool headLight() const;
+ bool parkLight() const;
+ int carId() const;
+ bool brake() const;
+ int engineTemp() const;
+ double oilTemp() const;
+ int oilPressure() const;
+ double batteryPotential() const;
+ double gasLevel() const;
+ int rpm() const;
+ int gear() const;
+Q_SIGNALS:
+ void vehicleSpeedChanged(double vehicleSpeed);
+ void latitudeChanged(double latitude);
+ void longitudeChanged(double longitude);
+ void directionChanged(double direction);
+ void flatTireChanged(bool flatTire);
+ void doorOpenChanged(bool doorOpen);
+ void lightFailureChanged(bool lightFailure);
+ void reverseChanged(bool Reverse);
+ void leftTurnLightChanged(bool leftTurnLight);
+ void rightTurnLightChanged(bool rightTurnLight);
+ void headLightChanged(bool headLight);
+ void parkLightChanged(bool parkLight);
+ void carIdChanged(int carId);
+ void brakeChanged(bool brakeOn );
+ void engineTempChanged(int engineTemp);
+ void oilTempChanged(double oilTemp);
+ void oilPressureChanged(int oilPressure);
+ void batteryPotentialChanged(double batteryPotential);
+ void gasLevelChanged(double gasLevel);
+ void rpmChanged(int rpm);
+ void gearChanged(int gear);
+ void zonesChanged();
+protected:
+ virtual void classBegin();
+ virtual void componentComplete();
+private Q_SLOTS:
+ void onVehicleSpeedChanged(double vehicleSpeed, const QString &zone);
+ void onLatitudeChanged(double latitude, const QString &zone);
+ void onLongitudeChanged(double longitude, const QString &zone);
+ void onDirectionChanged(double direction, const QString &zone);
+ void onFlatTireChanged(bool flatTire, const QString &zone);
+ void onDoorOpenChanged(bool doorOpen, const QString &zone);
+ void onLightFailureChanged(bool lightFailure, const QString &zone);
+ void onReverseChanged(bool reverse, const QString &zone);
+ void onLeftTurnLightChanged(bool leftTurnLight, const QString &zone);
+ void onRightTurnLightChanged(bool rightTurnLight, const QString &zone);
+ void onHeadLightChanged(bool headLight, const QString &zone);
+ void onParkLightChanged(bool parkLight, const QString &zone);
+ void onCarIdChanged(int carId, const QString &zone);
+ void onBrakeChanged(bool brakeOn, const QString &zone );
+ void onEngineTempChanged(int engineTemp, const QString &zone);
+ void onOilTempChanged(double oilTemp, const QString &zone);
+ void onOilPressureChanged(int oilPressure, const QString &zone);
+ void onBatteryPotentialChanged(double batteryPotential, const QString &zone);
+ void onGasLevelChanged(double gasLevel, const QString &zone);
+ void onRpmChanged(int rpm, const QString &zone);
+ void onGearChanged(int gear, const QString &zone);
+protected:
+private:
+ void connectToServiceObject();
+ QVariantMap zoneFeatureMap() const;
+ void initializeZones();
+ ZonedProperties *zoneAt(const QString &zone) const;
+private:
+ ClusterDataBackend *backend;
+ double m_vehicleSpeed;
+ double m_latitude;
+ double m_longitude;
+ double m_direction;
+ bool m_flatTire;
+ bool m_doorOpen;
+ bool m_lightFailure;
+ bool m_reverse;
+ bool m_leftTurnLight;
+ bool m_rightTurnLight;
+ bool m_headLight;
+ bool m_parkLight;
+ int m_carId;
+ bool m_brake;
+ qint8 m_engineTemp;
+ double m_oilTemp;
+ int m_oilPressure;
+ double m_batteryPotential;
+ double m_gasLevel;
+ int m_rpm;
+ int m_gear;
+ QVariantMap m_zoneFeatureMap;
+ QList<ZonedProperties*> m_zoneFeatures;
+ QVariantList m_zoneFeatureList;
+};
+
+#endif // CLUSTERDATA_H
diff --git a/CenterConsole/plugins/datasource/datasource.cpp b/CenterConsole/plugins/datasource/datasource.cpp
new file mode 100644
index 0000000..457c31d
--- /dev/null
+++ b/CenterConsole/plugins/datasource/datasource.cpp
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "datasource.h"
+
+DataSource::DataSource(QQuickItem *parent):
+ QQuickItem(parent)
+{
+ // By default, QQuickItem does not draw anything. If you subclass
+ // QQuickItem to create a visual item, you will need to uncomment the
+ // following line and re-implement updatePaintNode()
+
+ // setFlag(ItemHasContents, true);
+}
+
+DataSource::~DataSource()
+{
+}
+
diff --git a/CenterConsole/plugins/datasource/datasource.h b/CenterConsole/plugins/datasource/datasource.h
new file mode 100644
index 0000000..11d97b7
--- /dev/null
+++ b/CenterConsole/plugins/datasource/datasource.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef DATASOURCE_H
+#define DATASOURCE_H
+
+#include <QQuickItem>
+
+class DataSource : public QQuickItem
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(DataSource)
+
+public:
+ DataSource(QQuickItem *parent = 0);
+ ~DataSource();
+};
+
+QML_DECLARE_TYPE(DataSource)
+
+#endif // DATASOURCE_H
+
diff --git a/CenterConsole/plugins/datasource/datasource.pro b/CenterConsole/plugins/datasource/datasource.pro
new file mode 100644
index 0000000..8dd0d60
--- /dev/null
+++ b/CenterConsole/plugins/datasource/datasource.pro
@@ -0,0 +1,30 @@
+include (../../../deployment.pri)
+TEMPLATE = lib
+TARGET = qmldatasources
+QT += qml quick sql
+CONFIG += qt plugin
+
+TARGET = $$qtLibraryTarget($$TARGET)
+uri = com.pelagicore.datasource
+
+# Input
+SOURCES += \
+ sqlquerydatasource.cpp \
+ plugin.cpp \
+ sqlquerymodel.cpp \
+ sqltablemodel.cpp \
+ sqltabledatasource.cpp
+
+HEADERS += \
+ sqlquerydatasource.h \
+ plugin.h \
+ sqlquerymodel.h \
+ sqltablemodel.h \
+ sqltabledatasource.h
+
+OTHER_FILES = qmldir
+
+qmldir.files = qmldir
+qmldir.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+target.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+INSTALLS += target qmldir
diff --git a/CenterConsole/plugins/datasource/plugin.cpp b/CenterConsole/plugins/datasource/plugin.cpp
new file mode 100644
index 0000000..ee53f2c
--- /dev/null
+++ b/CenterConsole/plugins/datasource/plugin.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "plugin.h"
+
+#include <qqml.h>
+
+#include "sqlquerydatasource.h"
+#include "sqltabledatasource.h"
+
+void Plugin::registerTypes(const char *uri)
+{
+ // @uri com.pelagicore.datasource
+ qmlRegisterType<SqlQueryDataSource>(uri, 1, 0, "SqlQueryDataSource");
+ qmlRegisterType<SqlTableDataSource>(uri, 1, 0, "SqlTableDataSource");
+}
+
+
diff --git a/CenterConsole/plugins/datasource/plugin.h b/CenterConsole/plugins/datasource/plugin.h
new file mode 100644
index 0000000..0e268f1
--- /dev/null
+++ b/CenterConsole/plugins/datasource/plugin.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include <QQmlExtensionPlugin>
+
+class Plugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
+
+public:
+ void registerTypes(const char *uri);
+};
+
+#endif // PLUGIN_H
diff --git a/CenterConsole/plugins/datasource/qmldir b/CenterConsole/plugins/datasource/qmldir
new file mode 100644
index 0000000..213a63d
--- /dev/null
+++ b/CenterConsole/plugins/datasource/qmldir
@@ -0,0 +1,3 @@
+module com.pelagicore.datasource
+plugin qmldatasources
+
diff --git a/CenterConsole/plugins/datasource/sqlquerydatasource.cpp b/CenterConsole/plugins/datasource/sqlquerydatasource.cpp
new file mode 100644
index 0000000..723a4fa
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqlquerydatasource.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "sqlquerydatasource.h"
+#include "sqlquerymodel.h"
+
+SqlQueryDataSource::SqlQueryDataSource(QObject *parent)
+ : QObject(parent)
+ , m_storageLocation(QDir::homePath())
+ , m_model(new SqlQueryModel(this))
+ , m_status(SqlQueryDataSource::Null)
+{
+ connect(m_model, &SqlQueryModel::rowsInserted, this, &SqlQueryDataSource::countChanged);
+ connect(m_model, &SqlQueryModel::rowsRemoved, this, &SqlQueryDataSource::countChanged);
+ connect(m_model, &SqlQueryModel::layoutChanged, this, &SqlQueryDataSource::countChanged);
+ connect(m_model, &SqlQueryModel::modelReset, this, &SqlQueryDataSource::countChanged);
+}
+
+QVariantMap SqlQueryDataSource::get(int index) const
+{
+ if (!m_model) { return QVariantMap(); }
+ return m_model->get(index);
+}
+
+QString SqlQueryDataSource::database() const
+{
+ return m_database.connectionName();
+}
+
+SqlQueryDataSource::Status SqlQueryDataSource::status() const
+{
+ return m_status;
+}
+
+
+int SqlQueryDataSource::count() const
+{
+ if (!m_model) { return 0; }
+ return m_model->rowCount();
+}
+
+QString SqlQueryDataSource::query() const
+{
+ if (!m_query.isValid()) {
+ return QString();
+ }
+ return m_query.lastQuery();
+}
+
+void SqlQueryDataSource::setQuery(QString queryString)
+{
+ qDebug() << "SqlQueryDataSource::setQuery() " << queryString;
+ if (m_queryString != queryString) {
+ m_queryString = queryString;
+ updateModel();
+ emit queryChanged(queryString);
+ }
+}
+
+void SqlQueryDataSource::setDatabase(QString databaseName)
+{
+ if (m_databaseName != databaseName) {
+ m_databaseName = databaseName;
+ updateModel();
+ emit databaseChanged(databaseName);
+ }
+}
+
+void SqlQueryDataSource::updateModel()
+{
+ if (m_databaseName.isEmpty() || m_queryString.isEmpty()) {
+ setStatus(Null);
+ return;
+ }
+ if (!m_databaseName.isEmpty()) {
+ if (QSqlDatabase::contains(m_databaseName)) {
+ m_database = QSqlDatabase::database(m_databaseName);
+ } else {
+ m_database = QSqlDatabase::addDatabase("QSQLITE", m_databaseName);
+ QString databasePath = QDir(m_storageLocation).filePath(m_databaseName + ".db");
+ m_database.setDatabaseName(databasePath);
+ qDebug() << "database path: " << databasePath;
+ }
+ if (!m_database.isOpen()) {
+ m_database.open();
+ }
+ }
+ if (m_database.isValid() && !m_queryString.isEmpty()) {
+ setStatus(Loading);
+ m_query = QSqlQuery(m_queryString, m_database);
+ m_model->setQuery(m_query);
+ m_model->updateRoleNames();
+ if (m_query.lastError().isValid()) {
+ qDebug() << "Error" << m_query.lastError().text();
+ setStatus(Error);
+ } else {
+ setStatus(Ready);
+ }
+ }
+ emit modelChanged(m_model);
+}
+
+
+QObject *SqlQueryDataSource::model() const
+{
+ return m_model;
+}
+
+
+void SqlQueryDataSource::setStatus(SqlQueryDataSource::Status arg)
+{
+ if (m_status != arg) {
+ m_status = arg;
+ emit statusChanged(arg);
+ }
+}
+
+QString SqlQueryDataSource::storageLocation() const
+{
+ return m_storageLocation;
+}
+
+void SqlQueryDataSource::setStorageLocation(QString path)
+{
+ m_storageLocation = QDir(path).absolutePath();
+}
+
diff --git a/CenterConsole/plugins/datasource/sqlquerydatasource.h b/CenterConsole/plugins/datasource/sqlquerydatasource.h
new file mode 100644
index 0000000..eaf92f1
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqlquerydatasource.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef SQLQUERYDATASOURCE_H
+#define SQLQUERYDATASOURCE_H
+
+#include <QtCore>
+#include <QtSql>
+
+class SqlQueryModel;
+
+class SqlQueryDataSource : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString query READ query WRITE setQuery NOTIFY queryChanged)
+ Q_PROPERTY(QString database READ database WRITE setDatabase NOTIFY databaseChanged)
+ Q_PROPERTY(QObject* model READ model NOTIFY modelChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_PROPERTY(QString storageLocation READ storageLocation WRITE setStorageLocation NOTIFY storageLocationChanged)
+ Q_ENUMS(Status)
+
+public:
+ enum Status { Null, Loading, Ready, Error };
+ explicit SqlQueryDataSource(QObject *parent = 0);
+
+ void setQuery(QString queryString);
+ QString query() const;
+
+ QString database() const;
+ void setDatabase(QString databaseName);
+
+ int count() const;
+ Q_INVOKABLE QVariantMap get(int index) const;
+
+ QObject* model() const;
+
+ Status status() const;
+
+ QString storageLocation() const;
+ void setStorageLocation(QString path);
+private:
+ void updateModel();
+ void setStatus(Status arg);
+
+
+signals:
+ void countChanged();
+ void queryChanged(QString query);
+
+ void databaseChanged(QString arg);
+ void statusChanged(Status arg);
+
+ void modelChanged(QObject* model);
+ void storageLocationChanged();
+
+private:
+ QString m_queryString;
+ QString m_databaseName;
+ QString m_storageLocation;
+ SqlQueryModel *m_model;
+ QSqlQuery m_query;
+ QSqlDatabase m_database;
+ Status m_status;
+};
+
+
+
+#endif // SQLQUERYMODEL_H
diff --git a/CenterConsole/plugins/datasource/sqlquerymodel.cpp b/CenterConsole/plugins/datasource/sqlquerymodel.cpp
new file mode 100644
index 0000000..2b7aeb5
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqlquerymodel.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "sqlquerymodel.h"
+
+SqlQueryModel::SqlQueryModel(QObject *parent) :
+ QSqlQueryModel(parent)
+{
+}
+
+void SqlQueryModel::updateRoleNames()
+{
+ m_roleNames.clear();
+ for (int i = 0; i < record().count(); i++) {
+ m_roleNames[Qt::UserRole + i + 1] = record().fieldName(i).toLatin1();
+ }
+}
+
+QHash<int, QByteArray> SqlQueryModel::roleNames() const
+{
+ return m_roleNames;
+}
+
+QVariantMap SqlQueryModel::get(int row) const
+{
+ QVariantMap map;
+ QModelIndex index = createIndex(row, 0);
+ foreach (int role, m_roleNames.keys()) {
+ map.insert(m_roleNames.value(role), data(index, role));
+ }
+ return map;
+}
+
+QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
+{
+ QVariant value = QSqlQueryModel::data(index, role);
+ if (role < Qt::UserRole) {
+ value = QSqlQueryModel::data(index, role);
+ } else {
+ int columnIdx = role - Qt::UserRole - 1;
+ QModelIndex modelIndex = this->index(index.row(), columnIdx);
+ value = QSqlQueryModel::data(modelIndex, Qt::DisplayRole);
+ }
+ return value;
+}
+
+
+
diff --git a/CenterConsole/plugins/datasource/sqlquerymodel.h b/CenterConsole/plugins/datasource/sqlquerymodel.h
new file mode 100644
index 0000000..fde340f
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqlquerymodel.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef SQLQUERYMODEL_H
+#define SQLQUERYMODEL_H
+
+#include <QtSql/QSqlQueryModel>
+#include <QtSql/QSqlRecord>
+
+class SqlQueryModel : public QSqlQueryModel
+{
+ Q_OBJECT
+public:
+ explicit SqlQueryModel(QObject *parent = 0);
+ void updateRoleNames();
+ QHash<int, QByteArray> roleNames() const;
+ QVariantMap get(int row) const;
+ QVariant data(const QModelIndex &item, int role) const;
+private:
+ QHash<int, QByteArray> m_roleNames;
+};
+
+#endif // SQLQUERYMODEL_H
diff --git a/CenterConsole/plugins/datasource/sqltabledatasource.cpp b/CenterConsole/plugins/datasource/sqltabledatasource.cpp
new file mode 100644
index 0000000..9beebcb
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqltabledatasource.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "sqltabledatasource.h"
+#include "sqltablemodel.h"
+
+#include <QtCore/QtDebug>
+#include <QtCore/QStandardPaths>
+#include <QtCore/QDir>
+#include <QtSql/QSqlError>
+
+
+SqlTableDataSource::SqlTableDataSource(QObject *parent)
+ : QObject(parent)
+ , m_model(0)
+ , m_status(Null)
+ , m_componentCompleted(false)
+{
+}
+
+QString SqlTableDataSource::table() const
+{
+ return m_tableName;
+}
+
+QString SqlTableDataSource::database() const
+{
+ return m_databaseName;
+}
+
+QAbstractItemModel *SqlTableDataSource::model() const
+{
+ return m_model;
+}
+
+int SqlTableDataSource::count() const
+{
+ if (!m_model) { return 0; }
+ return m_model->rowCount();
+}
+
+SqlTableDataSource::Status SqlTableDataSource::status() const
+{
+ return m_status;
+}
+
+void SqlTableDataSource::setStatus(SqlTableDataSource::Status status)
+{
+ if (m_status != status) {
+ m_status = status;
+ emit statusChanged(status);
+ }
+}
+
+QString SqlTableDataSource::filter() const
+{
+ return m_model->filter();
+}
+
+QVariantMap SqlTableDataSource::get(int index) const
+{
+ if (!m_model) { return QVariantMap(); }
+ return m_model->get(index);
+}
+
+void SqlTableDataSource::classBegin()
+{
+}
+
+void SqlTableDataSource::componentComplete()
+{
+ qDebug() << "componentComplete";
+ m_componentCompleted = true;
+ updateModel();
+}
+
+QString SqlTableDataSource::storageLocation() const
+{
+ return QDir::homePath();
+}
+
+void SqlTableDataSource::setFilter(QString filter)
+{
+ qDebug() << "SqlTableDataSource::setFilter(): " << filter;
+ if (m_model->filter() != filter) {
+ m_model->setFilter(filter);
+ m_model->select();
+ emit filterChanged(filter);
+ }
+}
+
+void SqlTableDataSource::setTable(QString tableName)
+{
+ if (m_tableName != tableName) {
+ m_tableName = tableName;
+ updateModel();
+ emit tableChanged(tableName);
+ }
+}
+
+void SqlTableDataSource::setDatabase(QString databaseName)
+{
+ if (m_databaseName != databaseName) {
+ m_databaseName = databaseName;
+ updateModel();
+ emit databaseChanged(databaseName);
+ }
+}
+
+
+void SqlTableDataSource::updateModel()
+{
+ if (!m_componentCompleted) { return; }
+ qDebug() << "SqlTableDataSource::updateModel()";
+ if (m_databaseName.isEmpty() || m_tableName.isEmpty()) {
+ setStatus(Null);
+ qDebug() << " not configure; return";
+ return;
+ }
+ if (!m_databaseName.isEmpty()) {
+ if (QSqlDatabase::contains(m_databaseName)) {
+ qDebug() << " found existing db connection";
+ m_database = QSqlDatabase::database(m_databaseName);
+ } else {
+ qDebug() << " init new db connection";
+ m_database = QSqlDatabase::addDatabase("QSQLITE", m_databaseName);
+ QString databasePath = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(m_databaseName + ".db");
+ m_database.setDatabaseName(databasePath);
+ qDebug() << "database path: " << databasePath;
+ }
+ if (!m_database.isOpen()) {
+ qDebug() << " open database";
+ m_database.open();
+ qDebug() << " tables: " << m_database.tables();
+ }
+ }
+ if (m_database.isValid() && !m_tableName.isEmpty()) {
+ if (!m_model || m_model->tableName() != m_tableName) {
+ if (m_model) {
+ delete m_model;
+ m_model = 0;
+ emit modelChanged(m_model);
+ }
+ m_model = new SqlTableModel(this, m_database);
+ emit modelChanged(m_model);
+ }
+ qDebug() << " update table";
+ setStatus(Loading);
+ m_model->setTable(m_tableName);
+ qDebug() << " update role names";
+ m_model->updateRoleNames();
+ qDebug() << " select data";
+ if (!m_model->select()) {
+ qDebug() << " error: select data from model";
+ }
+ while (m_model->canFetchMore()) {
+ m_model->fetchMore(QModelIndex());
+ }
+ qDebug() << " finish select data";
+ if (m_model->lastError().isValid()) {
+ qDebug() << " error: " << m_model->lastError().text();
+ setStatus(Error);
+ } else {
+ qDebug() << " ready";
+ setStatus(Ready);
+ }
+ }
+ qDebug() << "update model: " << count();
+ emit modelChanged(m_model);
+ emit countChanged(count());
+}
+
diff --git a/CenterConsole/plugins/datasource/sqltabledatasource.h b/CenterConsole/plugins/datasource/sqltabledatasource.h
new file mode 100644
index 0000000..cbb94a3
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqltabledatasource.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef SQLTABLEDATASOURCE_H
+#define SQLTABLEDATASOURCE_H
+
+#include <QtCore/QAbstractItemModel>
+#include <QtSql/QSqlDatabase>
+#include <QtQml/QQmlParserStatus>
+
+class SqlTableModel;
+
+class SqlTableDataSource : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+ Q_PROPERTY(QString database READ database WRITE setDatabase NOTIFY databaseChanged)
+ Q_PROPERTY(QString table READ table WRITE setTable NOTIFY tableChanged)
+ Q_PROPERTY(QString filter READ filter WRITE setFilter NOTIFY filterChanged)
+ Q_PROPERTY(QObject* model READ model NOTIFY modelChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+ Q_PROPERTY(QString storageLocation READ storageLocation CONSTANT)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+ Q_ENUMS(Status)
+
+public:
+ enum Status { Null, Loading, Ready, Error };
+ explicit SqlTableDataSource(QObject *parent = 0);
+
+ QString table() const;
+ void setTable(QString tableName);
+
+ QString database() const;
+ void setDatabase(QString databaseName);
+
+ QAbstractItemModel* model() const;
+ int count() const;
+ Status status() const;
+ void setStatus(Status status);
+ QString filter() const;
+
+ Q_INVOKABLE QVariantMap get(int index) const;
+ // parser status
+ void classBegin();
+ void componentComplete();
+
+ QString storageLocation() const;
+
+public slots:
+ void setFilter(QString filter);
+
+signals:
+ void tableChanged(QString table);
+ void databaseChanged(QString database);
+ void countChanged(int count);
+ void statusChanged(Status status);
+ void modelChanged(QObject* model);
+ void filterChanged(QString arg);
+
+private:
+ void updateModel();
+private:
+ QString m_tableName;
+ QString m_databaseName;
+ QSqlDatabase m_database;
+ SqlTableModel* m_model;
+ Status m_status;
+ QString m_filter;
+ bool m_componentCompleted;
+};
+
+#endif // SQLTABLEDATASOURCE_H
diff --git a/CenterConsole/plugins/datasource/sqltablemodel.cpp b/CenterConsole/plugins/datasource/sqltablemodel.cpp
new file mode 100644
index 0000000..7b3179e
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqltablemodel.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "sqltablemodel.h"
+
+#include <QtCore/QtDebug>
+#include <QtSql/QSqlRecord>
+
+SqlTableModel::SqlTableModel(QObject *parent, QSqlDatabase db) :
+ QSqlTableModel(parent, db)
+{
+ connect(this, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(notifyCount()));
+ connect(this, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(notifyCount()));
+
+}
+
+void SqlTableModel::updateRoleNames()
+{
+ qDebug() << "SqlTableModel::updateRoleNames()";
+ m_roleNames.clear();
+ for (int i = 0; i < record().count(); i++) {
+ m_roleNames[Qt::UserRole + i + 1] = record().fieldName(i).toLatin1();
+ }
+ qDebug() << " role names: " << m_roleNames.values();
+}
+
+
+QHash<int, QByteArray> SqlTableModel::roleNames() const
+{
+ return m_roleNames;
+}
+
+
+QVariantMap SqlTableModel::get(int row) const
+{
+ QVariantMap map;
+ QModelIndex index = createIndex(row, 0);
+ foreach (int role, m_roleNames.keys()) {
+ map.insert(m_roleNames.value(role), data(index, role));
+ }
+ return map;
+}
+
+QVariant SqlTableModel::data(const QModelIndex &index, int role) const
+{
+ QVariant value = QSqlTableModel::data(index, role);
+ if (role < Qt::UserRole) {
+ value = QSqlTableModel::data(index, role);
+ } else {
+ int columnIdx = role - Qt::UserRole - 1;
+ QModelIndex modelIndex = this->index(index.row(), columnIdx);
+ value = QSqlTableModel::data(modelIndex, Qt::DisplayRole);
+ }
+ return value;
+}
+
+int SqlTableModel::count() const
+{
+ return rowCount();
+}
+
+void SqlTableModel::notifyCount()
+{
+ emit countChanged(rowCount());
+}
+
diff --git a/CenterConsole/plugins/datasource/sqltablemodel.h b/CenterConsole/plugins/datasource/sqltablemodel.h
new file mode 100644
index 0000000..736a30d
--- /dev/null
+++ b/CenterConsole/plugins/datasource/sqltablemodel.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef SQLTABLEMODEL_H
+#define SQLTABLEMODEL_H
+
+#include <QtSql/QSqlTableModel>
+
+class SqlTableModel : public QSqlTableModel
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+public:
+ explicit SqlTableModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
+
+ void updateRoleNames();
+ QHash<int, QByteArray> roleNames() const;
+ Q_INVOKABLE QVariantMap get(int row) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ int count() const;
+private slots:
+ void notifyCount();
+signals:
+ void countChanged(int count);
+
+private:
+ QHash<int, QByteArray> m_roleNames;
+};
+
+#endif // SQLTABLEMODEL_H
diff --git a/CenterConsole/plugins/plugins.pro b/CenterConsole/plugins/plugins.pro
new file mode 100644
index 0000000..f7a91e6
--- /dev/null
+++ b/CenterConsole/plugins/plugins.pro
@@ -0,0 +1,6 @@
+TEMPLATE = subdirs
+
+SUBDIRS = \
+ clusterdatasource \
+ datasource \
+ screenManager
diff --git a/CenterConsole/plugins/screenManager/plugin.cpp b/CenterConsole/plugins/screenManager/plugin.cpp
new file mode 100644
index 0000000..f4639a2
--- /dev/null
+++ b/CenterConsole/plugins/screenManager/plugin.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include <QtQml/qqmlextensionplugin.h>
+#include <qqml.h>
+#include "screenmanager.h"
+
+static QObject *screenManagerSingletonFactory(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(scriptEngine)
+ Q_UNUSED(engine)
+
+ return new ScreenManager();
+}
+
+class HoundPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("com.pelagicore.ScreenManager"));
+ Q_UNUSED(uri);
+
+ qmlRegisterSingletonType<ScreenManager>(uri, 1, 0, "ScreenManager", screenManagerSingletonFactory);
+ }
+};
+
+#include "plugin.moc"
diff --git a/CenterConsole/plugins/screenManager/qmldir b/CenterConsole/plugins/screenManager/qmldir
new file mode 100644
index 0000000..5472c91
--- /dev/null
+++ b/CenterConsole/plugins/screenManager/qmldir
@@ -0,0 +1,2 @@
+module com.pelagicore.ScreenManager
+plugin screenmanagerplugin
diff --git a/CenterConsole/plugins/screenManager/screenManager.pro b/CenterConsole/plugins/screenManager/screenManager.pro
new file mode 100644
index 0000000..44a0a0c
--- /dev/null
+++ b/CenterConsole/plugins/screenManager/screenManager.pro
@@ -0,0 +1,23 @@
+include (../../../deployment.pri)
+TEMPLATE = lib
+TARGET = screenmanagerplugin
+QT += qml quick
+CONFIG += qt plugin c++11
+
+TARGET = $$qtLibraryTarget($$TARGET)
+uri = com.pelagicore.ScreenManager
+
+SOURCES += \
+ plugin.cpp \
+ screenmanager.cpp \
+
+HEADERS += \
+ screenmanager.h \
+
+OTHER_FILES = qmldir
+
+qmldir.files = qmldir
+
+qmldir.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+target.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+INSTALLS += target qmldir
diff --git a/CenterConsole/plugins/screenManager/screenmanager.cpp b/CenterConsole/plugins/screenManager/screenmanager.cpp
new file mode 100644
index 0000000..06bc4dc
--- /dev/null
+++ b/CenterConsole/plugins/screenManager/screenmanager.cpp
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#include "screenmanager.h"
+#include <QGuiApplication>
+#include <QScreen>
+#include <QDebug>
+
+ScreenManager::ScreenManager(QObject *parent)
+ : QObject(parent)
+{
+ connect(qApp, &QGuiApplication::screenAdded, this, &ScreenManager::availableScreensChanged);
+ connect(qApp, &QGuiApplication::screenAdded, this, &ScreenManager::availableScreensChanged);
+}
+
+void ScreenManager::setScreen(QWindow *window, int screen)
+{
+ if (screen >= 0 && screen < QGuiApplication::screens().count()) {
+ window->setScreen(QGuiApplication::screens().at(screen));
+ } else {
+ qWarning() << "invalid Screen";
+ }
+}
+
+QList<QScreen *> ScreenManager::availableScreens() const
+{
+ return QGuiApplication::screens();
+}
+
+int ScreenManager::screenCount() const
+{
+ return QGuiApplication::screens().count();
+}
+
diff --git a/CenterConsole/plugins/screenManager/screenmanager.h b/CenterConsole/plugins/screenManager/screenmanager.h
new file mode 100644
index 0000000..b12f860
--- /dev/null
+++ b/CenterConsole/plugins/screenManager/screenmanager.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+#ifndef SCREENMANAGER_H
+#define SCREENMANAGER_H
+
+#include <QtCore/QObject>
+#include <QWindow>
+
+class ScreenManager : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QList<QScreen*> availableScreens READ availableScreens NOTIFY availableScreensChanged)
+
+public:
+ explicit ScreenManager(QObject *parent = 0);
+
+ Q_INVOKABLE int screenCount() const;
+ Q_INVOKABLE void setScreen(QWindow * window, int screen);
+ QList<QScreen*> availableScreens() const;
+
+signals:
+ void availableScreensChanged();
+};
+
+#endif // SCREENMANAGER_H
diff --git a/CenterConsole/plugins/scripts/README.md b/CenterConsole/plugins/scripts/README.md
new file mode 100644
index 0000000..94f1060
--- /dev/null
+++ b/CenterConsole/plugins/scripts/README.md
@@ -0,0 +1,9 @@
+# Scripts usage
+
+Scan scripts are used for for creating the SQL lite database and filling it with the music and movies. The data is later read with datasource project and in the end used from the QML.
+
+# Requirements
+
+Scan scripts require the mutagen Python package.
+
+https://bitbucket.org/lazka/mutagen
diff --git a/CenterConsole/plugins/scripts/scanmovies.py b/CenterConsole/plugins/scripts/scanmovies.py
new file mode 100644
index 0000000..b4786fe
--- /dev/null
+++ b/CenterConsole/plugins/scripts/scanmovies.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+
+"""
+/****************************************************************************
+**
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+"""
+
+# scanmovies.py
+# scans the ~/media/movies folder and generates all covers
+# and a ~/media.db database with alll tracks.
+
+import os
+import sqlite3 as db
+import argparse
+from mutagen.mp4 import MP4
+
+
+parser = argparse.ArgumentParser(description='scan movie folder')
+
+parser.add_argument('--source', default='~/media/movies', help='movie dir to scan')
+
+args = parser.parse_args()
+
+source = os.path.expanduser(args.source)
+
+albums = set()
+
+connection = db.connect(os.path.expanduser('~/media.db'))
+
+cursor = connection.cursor()
+
+
+sql_drop = 'drop table if exists movies'
+
+sql_create = """
+create table movies (
+ pk integer primary key,
+ title text,
+ year integer,
+ genre text,
+ desc text,
+ source text,
+ cover text
+ )
+"""
+
+sql_insert = """
+insert into movies (title,year,genre,desc,source,cover) VALUES (?,?,?,?,?,?)
+"""
+
+def createTable():
+ print('create table')
+ cursor.execute(sql_drop)
+ cursor.execute(sql_create)
+
+
+def extractTag(media, tag):
+ obj = media.get(tag)
+ if obj:
+ return ''.join(obj)#.encode('utf-8')
+ return ''
+
+def scanFolder(source):
+ print('scan folder: ' + source)
+ start = os.path.abspath(source)
+ for root, dirnames, filenames in os.walk(start):
+ for filename in filenames:
+ if not filename[-3:] == 'm4v':
+ continue
+ filepath = os.path.join(root, filename)
+ folderpath = os.path.relpath(root, start)
+ name = filename[0:-4]
+ print('analyze: ' + filepath)
+ try:
+ movie = MP4(filepath)
+ except:
+ print 'error reading: ', filepath
+ continue
+ title = extractTag(movie, '\xa9nam')
+ year = extractTag(movie, '\xa9day')
+ genre = extractTag(movie, '\xa9gen')
+ coverData = movie['covr'][0]
+ cover = os.path.join(folderpath, 'cover.jpg')
+ desc = extractTag(movie, 'desc')
+ source = os.path.join(folderpath, filename)
+ coverArt = file(os.path.join(start, cover), 'w')
+ coverArt.write(coverData)
+ coverArt.close()
+ cursor.execute(sql_insert, (title, year, genre, desc, source, cover))
+
+
+createTable()
+scanFolder(source)
+
+connection.commit()
diff --git a/CenterConsole/plugins/scripts/scanmusic.py b/CenterConsole/plugins/scripts/scanmusic.py
new file mode 100644
index 0000000..439935b
--- /dev/null
+++ b/CenterConsole/plugins/scripts/scanmusic.py
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+
+"""
+/****************************************************************************
+**
+** Copyright (C) 2016 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite licenses may use
+** this file in accordance with the commercial license agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and The Qt Company. For
+** licensing terms and conditions see https://www.qt.io/terms-conditions.
+** For further information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+"""
+
+# scanmusic.py
+# scans the ~/media/music folder and generates all covers
+# and a ~/media.db database with alll tracks.
+
+import os
+import sqlite3 as db
+import argparse
+from mutagen.id3 import ID3, ID3NoHeaderError
+
+
+parser = argparse.ArgumentParser(description='scan music folder')
+
+parser.add_argument('--source', default='~/media/music', help='music dir to scan')
+
+args = parser.parse_args()
+
+source = os.path.expanduser(args.source)
+
+albums = set()
+
+connection = db.connect(os.path.expanduser('~/media.db'))
+
+cursor = connection.cursor()
+
+
+sql_drop = 'drop table if exists music'
+
+sql_create = """
+create table music (
+ pk integer primary key,
+ album text,
+ title text,
+ track text,
+ artist text,
+ source text,
+ cover text
+ )
+"""
+
+sql_insert = """
+insert into music (album,title,track,artist,source,cover) VALUES (?,?,?,?,?,?)
+"""
+
+def createTable():
+ print('create table')
+ cursor.execute(sql_drop)
+ cursor.execute(sql_create)
+
+
+def extractTag(media, tag):
+ obj = media.get(tag)
+ if obj:
+ return ''.join(obj.text)#.encode('utf-8')
+ return ''
+
+def scanFolder(source):
+ print('scan folder: ' + source)
+ start = os.path.abspath(source)
+ for root, dirnames, filenames in os.walk(start):
+ for filename in filenames:
+ if not filename[-4:] == '.mp3':
+ continue
+ filepath = os.path.join(root, filename)
+ name = filename[0:-4]
+ folderpath = os.path.relpath(root, start)
+ print('analyze: ' + filepath)
+ try:
+ audio = ID3(filepath)
+ except ID3NoHeaderError:
+ print 'error reading: ', filepath
+ continue
+
+
+ # import pdb; pdb.set_trace()
+ title = extractTag(audio, 'TIT2')
+ album = extractTag(audio, 'TALB')
+ artist = extractTag(audio, 'TPE1')
+ track = extractTag(audio, 'TRCK')
+ source = os.path.join(folderpath, filename).decode('utf-8')
+
+ apics = audio.getall('APIC')[:1]
+ apic = None
+ if len(apics):
+ apic = apics[0]
+ coverName = ''
+ if apic:
+ if apic.mime == 'image/jpeg':
+ coverName = 'cover.jpg'
+ elif apic.mime == 'image/png':
+ coverName = 'cover.png'
+ else:
+ print('unknown cover mime type: ' + mime)
+ else:
+ import pdb; pdb.set_trace()
+ print('!!! NO COVER')
+
+ cover = os.path.join(folderpath, coverName).decode('utf-8')
+ album_id = '%s/%s'%(album, artist)
+ if not album_id in albums:
+ albums.add(album_id)
+ if apic: # save new cover
+ art = file(os.path.join(root, coverName), 'w')
+ art.write(apic.data)
+ art.close()
+ cursor.execute(sql_insert, (album, title, track, artist, source, cover))
+
+
+createTable()
+scanFolder(source)
+
+connection.commit()
+
+
+
diff --git a/CenterConsole/qml.qrc b/CenterConsole/qml.qrc
new file mode 100644
index 0000000..4d8ed66
--- /dev/null
+++ b/CenterConsole/qml.qrc
@@ -0,0 +1,3 @@
+<RCC>
+ <qresource prefix="/"/>
+</RCC>
diff --git a/CenterConsole/sysui/BottomBar/Aircondition.qml b/CenterConsole/sysui/BottomBar/Aircondition.qml
new file mode 100644
index 0000000..6028d1a
--- /dev/null
+++ b/CenterConsole/sysui/BottomBar/Aircondition.qml
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Controls 2.0
+import QtQuick.Layouts 1.0
+
+import utils 1.0
+import controls 1.0
+import service.climate 1.0
+
+Item {
+ id: root
+ property real startPoint: 0.5 * Math.PI
+ property real endPoint: 2 * Math.PI
+
+ property int ventilationLevels: ClimateService.ventilationLevels - 1
+ property int ventilation: ClimateService.ventilation
+
+ //Needed for swiping ventilation speed
+ property int previousMouseX: 0
+
+ //mouse.wasHeld does not work, create own
+ property bool wasHeld
+
+ property string activeFanDirection: "fandirection-windshieldandlegs"
+ property string backgroundImage: Style.symbol("fandirection-knob-up")
+
+ onActiveFanDirectionChanged: {
+ currentFanDirection.source = Style.symbol(activeFanDirection)
+ }
+
+ width: 290
+ height: Style.bottomBarHeight
+ state: ""
+ Image {
+ anchors.centerIn: parent
+ source: backgroundImage
+ }
+ Image {
+ anchors.centerIn: parent
+ z: 2
+ source: Style.symbol("MiddleMask")
+ }
+
+ Item {
+ id: fanDirection
+ visible: root.state === "ventilationSelection"
+ width: 400
+ height: parent.height
+ anchors.centerIn: parent
+ z: 3
+ Column {
+ id: leftSide
+ width: parent.width / 3
+ height: parent.height - 10
+ AirflowItem {
+ property alias fanDir: root.activeFanDirection
+ anchors.right: parent.right
+ icon: "fandirection-head"
+ climateId: ClimateService.airflow.dashboard
+ }
+ AirflowItem {property alias fanDir: root.activeFanDirection
+ icon: "fandirection-headandlegs"
+ climateId: ClimateService.airflow.floor | ClimateService.airflow.dashboard
+ }
+ AirflowItem {
+ property alias fanDir: root.activeFanDirection
+ anchors.horizontalCenter: parent.horizontalCenter
+ icon: "fandirection-legs"
+ climateId: ClimateService.airflow.floor
+ }
+ }
+
+ Column {
+ id: rightSide
+ anchors.right: parent.right
+ width: parent.width / 3
+ height: parent.height - 10
+ AirflowItem {
+ id: image
+ property alias fanDir: root.activeFanDirection
+ icon: "fandirection-windshield"
+ climateId: ClimateService.airflow.windshield
+ }
+ Item {id: spacer; height: image.height; width: image.width}
+ AirflowItem {
+ property alias fanDir: root.activeFanDirection
+ icon: "fandirection-windshieldandlegs"
+ anchors.horizontalCenter: parent.horizontalCenter
+ climateId: (ClimateService.airflow.windshield | ClimateService.airflow.floor)
+ }
+ }
+ }
+ Item {
+ id: centerImages
+ anchors.fill: parent
+ Column {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ Image {
+ id: currentFanDirection
+ source: Style.symbol(activeFanDirection)
+ }
+ Image {
+ source: root.state === "ventilationSelection"
+ ? Style.symbol("back") : Style.symbol("fandirection")
+ anchors.horizontalCenter: currentFanDirection.horizontalCenter
+ }
+ }
+
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ propagateComposedEvents: true
+ //enabled: root.state === ""
+ onReleased: {
+ //If mouse was held, then swipe happened. Then ignore click
+ if (wasHeld) {
+ wasHeld = false
+ return
+ }
+ if (root.state === "ventilationSelection")
+ root.state = ""
+ else
+ root.state = "ventilationSelection"
+ }
+ onPositionChanged: {
+ updateIndex(mouse.x)
+ mouse.accepted = true
+ }
+
+ function updateIndex(x) {
+ //Don't swipe too fast.
+ if (Math.abs(previousMouseX - x) < 10)
+ return
+ //Swiping right, increase ventioation
+ if ((x > previousMouseX ) && (root.ventilation < ventilationLevels))
+ root.ventilation++
+ //Swiping left, decrease ventioation
+ else if ((x < previousMouseX ) && (root.ventilation > 0))
+ root.ventilation--
+ previousMouseX = x
+ wasHeld = true
+ }
+ }
+
+ Item {
+ z: 13
+ x: 48
+ y: -10
+ Repeater {
+ model: root.ventilation
+ Image {
+ source: Style.symbol("Highlight")
+ rotation: index * 30
+ }
+ }
+ }
+ onStateChanged: {
+ state === "ventilationSelection" ? backgroundImage = Style.symbol("fandirection-knob-down")
+ : backgroundImage = Style.symbol("fandirection-knob-up")
+ }
+
+ states: [
+ State {
+ name: "ventilationSelection"
+ PropertyChanges {
+ target: fanDirection
+ visible: true
+ }
+ }
+ ]
+}
+
+
diff --git a/CenterConsole/sysui/BottomBar/AirflowItem.qml b/CenterConsole/sysui/BottomBar/AirflowItem.qml
new file mode 100644
index 0000000..bb1b5cd
--- /dev/null
+++ b/CenterConsole/sysui/BottomBar/AirflowItem.qml
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import controls 1.0
+import service.climate 1.0
+
+Symbol {
+ id: symbol
+ property string icon: ""
+ property var climateId: ""
+ scale: 0.7
+ name: icon
+ active: ClimateService.airflow.value === climateId
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (active)
+ ClimateService.airflow.value = 0
+ else
+ ClimateService.airflow.value = climateId
+ }
+ }
+ onActiveChanged: {
+ if (active === true)
+ symbol.fanDir = name
+ }
+}
diff --git a/CenterConsole/sysui/BottomBar/BottomBar.qml b/CenterConsole/sysui/BottomBar/BottomBar.qml
new file mode 100644
index 0000000..e0817e9
--- /dev/null
+++ b/CenterConsole/sysui/BottomBar/BottomBar.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+
+import controls 1.0
+import utils 1.0
+import service.climate 1.0
+
+Item {
+ id: bottomBar
+ width: Style.bottomBarWidth
+ height: Style.bottomBarHeight
+ Image {
+ source: Style.symbol("SimpleBottomBackground")
+ }
+
+ RowLayout {
+ id: row
+ anchors.fill: parent
+
+ TumblerTool {
+ id: tempLevelLeft
+ index: 10
+ Layout.fillWidth: true
+ anchors.verticalCenter: parent.verticalCenter
+ onIndexChanged: {
+ if (syncButton.checked === true)
+ tempLevelRight.index = tempLevelLeft.index
+ }
+ }
+ ButtonTool {
+ anchors.verticalCenter: parent.verticalCenter
+ text: "AUTO"
+ }
+ Aircondition {
+ anchors.verticalCenter: parent.verticalCenter
+ Layout.fillWidth: true
+ }
+ ButtonTool {
+ id: syncButton
+ anchors.verticalCenter: parent.verticalCenter
+ text: "SYNC"
+ onCheckChanged: {
+ if (check === true)
+ tempLevelRight.index = tempLevelLeft.index
+ }
+ }
+ TumblerTool {
+ id: tempLevelRight
+ Layout.fillWidth: true
+ index: 5
+ anchors.verticalCenter: parent.verticalCenter
+ onIndexChanged: {
+ if (syncButton.checked === true && tempLevelRight.index !== tempLevelLeft.index)
+ syncButton.checked = false
+ }
+ }
+ }
+}
diff --git a/CenterConsole/sysui/BottomBar/ButtonTool.qml b/CenterConsole/sysui/BottomBar/ButtonTool.qml
new file mode 100644
index 0000000..6e87938
--- /dev/null
+++ b/CenterConsole/sysui/BottomBar/ButtonTool.qml
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Controls 2.0
+
+import utils 1.0
+
+Button {
+ id: control
+ checkable: true
+ property alias buttonText: control.text
+
+ property bool check: control.checked
+ property string imageSource: Style.symbol("acautosync-knob-up")
+
+ contentItem: Item {
+ Text {
+ anchors.centerIn: parent
+ text: control.text
+ color: Style.colorWhite
+ font.pixelSize: Style.fontSizeXXS
+ }
+ }
+
+ background: Image {
+ id: backgroundImage
+ source: imageSource
+ }
+ onCheckChanged: {
+ if (checked)
+ imageSource = Style.symbol("acautosync-knob-down")
+ else
+ imageSource = Style.symbol("acautosync-knob-up")
+ }
+}
diff --git a/CenterConsole/sysui/BottomBar/TumblerTool.qml b/CenterConsole/sysui/BottomBar/TumblerTool.qml
new file mode 100644
index 0000000..fc5c8a4
--- /dev/null
+++ b/CenterConsole/sysui/BottomBar/TumblerTool.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Controls 2.0
+import QtGraphicalEffects 1.0
+
+import utils 1.0
+
+Item {
+ property real scaleFactor: 1.5
+ height: Style.bottomBarHeight
+ width: Style.tumblerWidth
+ property alias index: tempLevel.currentIndex
+// RadialGradient {
+// anchors.fill: parent
+// angle: 45
+// horizontalRadius: 100
+// verticalRadius: 80
+// gradient: Gradient {
+// GradientStop { position: 0.0; color: Style.colorRed }
+// GradientStop { position: 0.8; color: Style.darkGrey }
+// }
+// }
+
+ Tumbler {
+ id: tempLevel
+ z: 0
+ model: 8
+ anchors.fill: parent
+ visibleItemCount: 3
+
+ contentItem: ListView {
+ anchors.fill: parent
+ model: tempLevel.model
+ delegate: tempLevel.delegate
+ snapMode: ListView.SnapToItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ preferredHighlightBegin: height / 2 - (height / tempLevel.visibleItemCount / 2)
+ preferredHighlightEnd: height / 2 + (height / tempLevel.visibleItemCount / 2)
+ clip: true
+ }
+ delegate: Label {
+ text: ("%1 °").arg(modelData + 18)
+ font.pixelSize: Style.fontSizeL
+ scale: ListView.isCurrentItem ? scaleFactor : 1
+ horizontalAlignment: Text.AlignHCenter
+ opacity: 0.4 + Math.max(0, 1 - Math.abs(Tumbler.displacement)) * 0.6
+ color: Style.colorWhite
+ Behavior on scale {
+ NumberAnimation { duration: 200 }
+ }
+ }
+ }
+}
diff --git a/CenterConsole/sysui/CenterItems/ArrivalInfo.qml b/CenterConsole/sysui/CenterItems/ArrivalInfo.qml
new file mode 100644
index 0000000..b7ac99b
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/ArrivalInfo.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+import controls 1.0
+
+Column {
+ property string arText: arrival.text
+ property string text2: arrival2.text
+
+ Label {
+ id: arrival
+ text: arText
+ }
+ Label {
+ id: arrival2
+ text: text2
+ anchors.horizontalCenter: arrival.horizontalCenter
+ }
+}
diff --git a/CenterConsole/sysui/CenterItems/DestinationInfo.qml b/CenterConsole/sysui/CenterItems/DestinationInfo.qml
new file mode 100644
index 0000000..c29a6a5
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/DestinationInfo.qml
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+import controls 1.0
+import service.valuesource 1.0
+
+Rectangle {
+ id: root
+ width: Style.screenWidth
+ height: 210
+ color: "#303A48"
+ opacity: 0.8
+
+ Image{
+ id: closeButton
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: Style.paddingXXL
+ source: Style.symbol("cancel")
+ MouseArea{
+ anchors.fill: parent
+ onClicked: {
+ root.mapState = "selectDestination"
+ }
+ }
+ }
+ Column {
+ id: column
+ width: parent.width
+ anchors.top: parent.top
+ anchors.margins: Style.paddingXXL
+ spacing: 20
+ Label {
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "To " + ValueSource.destination
+ font.pixelSize: Style.fontSizeM
+ }
+ Label {
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "From " + ValueSource.currentLocation
+ }
+ Rectangle {
+ width: parent.width
+ height: 2
+ color: "#8E9399"
+ }
+ }
+
+ Rectangle {
+ color: "white"
+ anchors.top: column.bottom
+ anchors.topMargin: 10
+ anchors.left: parent.left
+ anchors.leftMargin: 80
+ height: Style.searchInputHeight
+ width: parent.width / 2 - 100
+ radius: Style.buttonRadius
+ Label {
+ id: txt
+ anchors.centerIn: parent
+ text: "Manual drive"
+ color: Style.colorPink
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.mapState = "driveStarted"
+ }
+ }
+ Rectangle {
+ color: "white"
+ anchors.top: column.bottom
+ anchors.right: parent.right
+ anchors.rightMargin: 80
+ anchors.topMargin: 10
+ height: Style.searchInputHeight
+ width: parent.width / 2 - 100
+ radius: Style.buttonRadius
+ Label {
+ anchors.centerIn: parent
+ text: "Autopilot"
+ color: Style.colorPink
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.mapState = "driveStarted"
+ }
+ }
+}
+
diff --git a/CenterConsole/sysui/CenterItems/HandwritingModeButton.qml b/CenterConsole/sysui/CenterItems/HandwritingModeButton.qml
new file mode 100644
index 0000000..0e1b534
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/HandwritingModeButton.qml
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+
+Item {
+ id: handwritingModeButton
+ state: "unavailable"
+ property bool floating
+ property bool flipable
+ readonly property real __minWidthHeight: Math.min(width, height)
+
+ signal pressed()
+ signal doubleClicked()
+
+ Flipable {
+ id: flipableImage
+ anchors.fill: parent
+
+ property bool flipped
+
+ front: Image {
+ sourceSize.width: handwritingModeButton.__minWidthHeight
+ sourceSize.height: handwritingModeButton.__minWidthHeight
+ smooth: false
+ source: Style.drawableUrl + '/' + "FloatingButton_Unavailable.svg"
+ }
+
+ back: Image {
+ id: buttonImage
+ sourceSize.width: handwritingModeButton.__minWidthHeight
+ sourceSize.height: handwritingModeButton.__minWidthHeight
+ smooth: false
+ source: Style.drawableUrl + '/' + "FloatingButton_Available.svg"
+ }
+
+ states: State {
+ PropertyChanges { target: rotation; angle: 180 }
+ when: flipableImage.flipped
+ }
+
+ transform: Rotation {
+ id: rotation
+ origin.x: flipableImage.width / 2
+ origin.y: flipableImage.height / 2
+ axis { x: 0; y: 1; z: 0 }
+ angle: 0
+ }
+
+ transitions: Transition {
+ enabled: handwritingModeButton.flipable
+ NumberAnimation { target: rotation; property: "angle"; duration: 400 }
+ }
+ }
+
+ states: [
+ State {
+ name: "available"
+ PropertyChanges { target: flipableImage; flipped: true }
+ },
+ State {
+ name: "active"
+ PropertyChanges { target: flipableImage; flipped: true }
+ PropertyChanges {
+ target: buttonImage
+ source: Style.drawableUrl + '/' + "FloatingButton_Active.svg"
+ }
+ }
+ ]
+
+ function snapHorizontal() {
+ if (!floating)
+ return
+ if (mouseArea.drag.maximumX > mouseArea.drag.minimumX) {
+ if (x + 20 >= mouseArea.drag.maximumX) {
+ anchors.left = undefined
+ anchors.right = parent.right
+ } else if (x - 20 <= mouseArea.drag.minimumX) {
+ anchors.right = undefined
+ anchors.left = parent.left
+ }
+ }
+ }
+
+ function snapVertical() {
+ if (!floating)
+ return
+ if (mouseArea.drag.maximumY > mouseArea.drag.minimumY) {
+ if (y + 20 >= mouseArea.drag.maximumY) {
+ anchors.top = undefined
+ anchors.bottom = parent.bottom
+ } else if (y - 20 <= mouseArea.drag.minimumY) {
+ anchors.bottom = undefined
+ anchors.top = parent.top
+ }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ drag {
+ target: handwritingModeButton.floating ? handwritingModeButton : undefined
+ axis: Drag.XAxis | Drag.YAxis
+ minimumX: 0
+ maximumX: handwritingModeButton.parent.width - handwritingModeButton.width
+ onMaximumXChanged: !mouseArea.drag.active && handwritingModeButton.snapHorizontal()
+ minimumY: 0
+ maximumY: handwritingModeButton.parent.height - handwritingModeButton.height
+ onMaximumYChanged: !mouseArea.drag.active && handwritingModeButton.snapVertical()
+ }
+ onClicked: {
+ if (!handwritingModeButton.floating)
+ return
+ handwritingModeButton.anchors.left = undefined
+ handwritingModeButton.anchors.top = undefined
+ handwritingModeButton.anchors.right = undefined
+ handwritingModeButton.anchors.bottom = undefined
+ }
+ onReleased: {
+ handwritingModeButton.snapHorizontal()
+ handwritingModeButton.snapVertical()
+ }
+// onClicked: {
+// handwritingModeButton.snapHorizontal()
+// handwritingModeButton.snapVertical()
+// clickTimer.restart()
+// }
+ onDoubleClicked: {
+ clickTimer.stop()
+ handwritingModeButton.snapHorizontal()
+ handwritingModeButton.snapVertical()
+ handwritingModeButton.doubleClicked()
+ }
+ Timer {
+ id: clickTimer
+ interval: Qt.styleHints ? Qt.styleHints.mouseDoubleClickInterval / 3 : 0
+ repeat: false
+ onTriggered: handwritingModeButton.pressed()
+ }
+ }
+}
diff --git a/CenterConsole/sysui/CenterItems/MapPOI.qml b/CenterConsole/sysui/CenterItems/MapPOI.qml
new file mode 100644
index 0000000..a8f4673
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/MapPOI.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import utils 1.0
+import controls 1.0
+
+Column {
+ property string poiText: "Shopping"
+ property string poiIcon: "placeofinterest-shopping"
+ spacing: Style.paddingL
+
+ Rectangle {
+ id: image
+ implicitWidth: poiImage.width * 2
+ implicitHeight: implicitWidth
+ radius: implicitWidth
+ color: Style.colorPink
+ Image {
+ id: poiImage
+ anchors.centerIn: parent
+ source: Style.symbol(poiIcon)
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ root.mapState = "showRoute"
+ Qt.inputMethod.hide()
+ }
+ }
+ }
+ Label {
+ text: poiText
+ anchors.horizontalCenter: image.horizontalCenter
+ font.pixelSize: Style.fontSizeXS
+ }
+}
diff --git a/CenterConsole/sysui/CenterItems/MapPage.qml b/CenterConsole/sysui/CenterItems/MapPage.qml
new file mode 100644
index 0000000..d87b13d
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/MapPage.qml
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtLocation 5.5
+import QtPositioning 5.5
+
+import controls 1.0
+import utils 1.0
+import service.valuesource 1.0
+import service.statusbar 1.0
+
+Item {
+ id: root
+ width: Style.screenWidth
+ height: parent.height
+ property var startCoordinate: QtPositioning.coordinate(52.53471566, 13.29339621)
+ property var endCoordinate: QtPositioning.coordinate(52.51329679, 13.32095033)
+ property bool navigationStarted: false
+ property string totalTravelTime
+ property string totalDistance
+ property string arrivalTime
+ property bool offlineMode: false
+
+ Image {
+ z: 2
+ source: Style.symbol("MapOverlayEdgeGradient")
+ }
+
+ Image {
+ z: 3
+ source: Style.symbol("Built_with_Qt_RGB_logo_white")
+ anchors.right: parent.right
+ anchors.top: parent.top
+
+ }
+
+ onNavigationStartedChanged: {
+ if (navigationStarted) {
+ ValueSource.automaticDemoMode = false
+ positionSource.start()
+ routeStopped.running = true
+ } else {
+ ValueSource.automaticDemoMode = true
+ positionSource.stop()
+ routeStopped.running = false
+ }
+ }
+
+ Map {
+ id: map
+ width: parent.width
+ height: parent.height
+ color: "black"
+ property real speed
+ property bool mapManuallyMoved: false
+ property bool flickStarted: false
+
+ plugin: Plugin {
+ id: plugin
+ preferred: ["mapbox"]
+ //This mapbox token is for this automotive demo use only. For other projects please contact
+ //https://www.mapbox.com/ for access token.
+ PluginParameter { name: "mapbox.access_token"; value: "pk.eyJ1IjoibWFwYm94NHF0IiwiYSI6ImNpd3J3eDE0eDEzdm8ydHM3YzhzajlrN2oifQ.keEkjqm79SiFDFjnesTcgQ" }
+ PluginParameter { name: "mapbox.map_id"; value: "qtcluster.d7eed331" }
+ }
+
+ center: startCoordinate
+
+ //Helper timer to notice when position is not updated anymore,
+ //then we need to start the route over.
+ Timer {
+ id: routeStopped
+ interval: 5000
+ running: false
+ onTriggered: {
+ positionSource.nmeaSource = ""
+ positionSource.nmeaSource = "route.txt"
+ positionSource.start()
+ }
+ }
+
+ PositionSource {
+ id: positionSource
+ nmeaSource: "route.txt"
+ onPositionChanged: {
+ if (position.speedValid) {
+ ValueSource.kph = position.speed
+ routeStopped.restart()
+ }
+ }
+ }
+
+ Behavior on center {
+ id: centerBehavior
+ enabled: true
+ CoordinateAnimation { duration: 1500 }
+ }
+
+ zoomLevel: 16
+ gesture.enabled: true
+ gesture.acceptedGestures: MapGestureArea.PinchGesture | MapGestureArea.PanGesture
+ | MapGestureArea.FlickGesture
+ gesture.onFlickFinished: {
+ flickStarted = false
+ checkMapMoving()
+ }
+ gesture.onFlickStarted: {
+ flickStarted = true
+ }
+ gesture.onPanFinished: {
+ if (!flickStarted)
+ checkMapMoving()
+ }
+ function checkMapMoving() {
+ if (!map.visibleRegion.contains(positionQuickItem.coordinate))
+ map.mapManuallyMoved = true
+ else
+ map.mapManuallyMoved = false
+ }
+
+ RouteModel {
+ id: routeModel
+ plugin: map.plugin
+ query: RouteQuery {
+ id: routeQuery
+ }
+ onRoutesChanged: {
+ totalTravelTime = routeModel.count == 0
+ ? "" : formatTime(routeModel.get(0).travelTime)
+ totalDistance = routeModel.count == 0
+ ? "" : formatDistance(routeModel.get(0).distance)
+ arrivalTime = routeModel.count == 0
+ ? "" : formatArrivalTime(routeModel.get(0).travelTime)
+ }
+ onErrorChanged:{
+ console.log("Map route error: "+errorString)
+ offlineMode = true
+ }
+ }
+
+ MapItemView {
+ model: routeModel
+ delegate: routeDelegate
+ autoFitViewport: true
+ }
+
+ Component {
+ id: routeDelegate
+
+ MapRoute {
+ id: route
+ route: routeData
+ line.color: Style.colorPink
+ line.width: 5
+ smooth: true
+ opacity: 0.8
+ }
+ }
+
+ MapQuickItem {
+ id: positionQuickItem
+ z: 3
+ coordinate: root.navigationStarted && positionSource.position.latitudeValid
+ ? positionSource.position.coordinate
+ : startCoordinate
+ anchorPoint.x: positionImage.width / 2
+ anchorPoint.y: positionImage.height / 2
+ sourceItem: Image {
+ id: positionImage
+ source: root.mapState === "enterCar"
+ ? Style.symbol("search") : Style.symbol("NavRoundmarker")
+ }
+ Behavior on coordinate {
+ enabled: true
+ CoordinateAnimation { duration: 1500 }
+ }
+ }
+ //In offline mode this replaces MapRoute
+ MapPolyline {
+ id: offlineRoute
+ visible: false
+ line.color: Style.colorPink
+ line.width: 5
+ opacity: 0.8
+ smooth: true
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ propagateComposedEvents: true
+ enabled: root.mapState === "selectDestination"
+ || root.mapState === "enterCar"
+ || root.mapState === "navigationRunning" ? true : false
+ onClicked: {
+ if (root.mapState === "navigationRunning")
+ root.mapState = "driveStarted"
+ else
+ root.mapState = "selectDestination"
+ }
+ }
+
+ Timer {
+ interval: 3000
+ repeat: true
+ running: !map.mapManuallyMoved && (root.mapState === "navigationRunning"
+ || root.mapState === "driveStarted")
+ onTriggered: {
+ //Check if positionQuickItem has moved out of visible area. We cannot do that in
+ //onCoordinageChanged function as that fires too often
+ if (map.mapManuallyMoved || map.panOngoing)
+ return
+ if (!map.visibleRegion.contains(positionQuickItem.coordinate))
+ map.center = positionQuickItem.coordinate
+ }
+ }
+ }
+
+ Image {
+ id: backButton
+ z: 3
+ anchors.left: parent.left
+ anchors.top: root.top
+ anchors.margins: 20
+ visible: (root.mapState !== "enterCar") && (root.mapState !== "navigationRunning")
+ source: Style.symbol("back-background")
+ MouseArea {
+ id: backArea
+ anchors.fill: parent
+ onClicked: {
+ //When back button is pressed, return to enter car screen.
+ //If navigation is running, then show navi info
+ if (root.mapState !== "driveStarted")
+ root.mapState = "enterCar"
+ else
+ root.mapState = "navigationRunning"
+
+ if (Qt.inputMethod.visible)
+ Qt.inputMethod.hide()
+ }
+ }
+ scale: backArea.pressed ? 0.85 : 1.0
+ Behavior on scale {
+ NumberAnimation {}
+ }
+ }
+
+ Image {
+ id: carFocusButton
+ z: 3
+ visible: map.mapManuallyMoved
+ source: Style.symbol("CarFocusButton")
+ anchors.right: parent.right
+ anchors.top: root.top
+ anchors.margins: 20
+ MouseArea {
+ id: area
+ anchors.fill: parent
+ onClicked: {
+ map.mapManuallyMoved = false
+ if (root.mapState === "navigationRunning" || root.mapState === "driveStarted")
+ map.center = positionSource.position.coordinate
+ else
+ map.center = startCoordinate
+ }
+ }
+ scale: area.pressed ? 0.85 : 1.0
+
+ Behavior on scale {
+ NumberAnimation {}
+ }
+ }
+
+ Label {
+ id: currentLocationText
+ z: 3
+ visible: !navigationStarted | root.mapState === "navigationRunning"
+ y: 20
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pixelSize: Style.fontSizeL
+ text: root.mapState === "navigationRunning" ? "DESTINATION" : "YOU ARE NOW AT"
+ }
+
+ Label {
+ id: currentLocationText2
+ z: 3
+ visible: !navigationStarted | root.mapState === "navigationRunning"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: currentLocationText.bottom
+ font.pixelSize: Style.fontSizeXL
+ text: root.mapState === "navigationRunning"
+ ? ValueSource.destination : ValueSource.currentLocation
+ }
+
+ Row {
+ visible: root.mapState === "navigationRunning"
+ z: 3
+ anchors.top: currentLocationText2.bottom
+ anchors.topMargin: Style.padding
+ anchors.horizontalCenter: currentLocationText2.horizontalCenter
+ spacing: Style.paddingXL
+ ArrivalInfo { arText: arrivalTime; text2: "arrival time" }
+ ArrivalInfo { arText: totalTravelTime; text2: "duration" }
+ ArrivalInfo { arText: totalDistance; text2: "distance" }
+ }
+
+ Label {
+ z: 3
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.leftMargin: Style.padding
+ anchors.topMargin:5
+ font.pixelSize: 9
+ text: "© Mapbox © OpenStreetMap"
+ }
+
+ function showRoute() {
+ if (offlineMode) {
+ console.log("application in offline mode")
+ var doc = new XMLHttpRequest();
+ doc.onreadystatechange = function() {
+ console.log("readychanged "+doc.readyState)
+ if (doc.readyState === XMLHttpRequest.DONE) {
+ var a = JSON.parse(doc.responseText)
+ offlineRoute.path = a
+ offlineRoute.visible = true
+ }
+ }
+ doc.open("GET", "offlineRoute.txt");
+ doc.send();
+ }
+ else {
+ routeQuery.clearWaypoints()
+
+ // add the start and end coords as waypoints on the route
+ routeQuery.addWaypoint(startCoordinate)
+ routeQuery.addWaypoint(endCoordinate)
+ routeQuery.travelModes = RouteQuery.CarTravel
+ routeQuery.routeOptimizations = RouteQuery.FastestRoute
+
+ routeModel.update()
+ }
+ }
+
+ function hideRoute() {
+ if (offlineMode) {
+ offlineRoute.visible = false
+ }
+ else {
+ routeQuery.clearWaypoints()
+ routeModel.reset()
+ routeModel.update()
+ }
+ }
+
+ function formatTime(sec)
+ {
+ var value = sec
+ var seconds = value % 60
+ value /= 60
+ value = (value > 1) ? Math.round(value) : 0
+ var minutes = value % 60
+ value /= 60
+ value = (value > 1) ? Math.round(value) : 0
+ var hours = value
+ if (hours > 0)
+ value = hours + "h:" + minutes + "m"
+ else
+ value = minutes + " min"
+ return value
+ }
+
+ function formatDistance(meters)
+ {
+ var dist = Math.round(meters)
+ if (dist > 1000) {
+ if (dist > 100000) {
+ dist = Math.round(dist / 1000)
+ } else {
+ dist = Math.round(dist / 100)
+ dist = dist / 10
+ }
+ dist = dist + " km"
+ } else {
+ dist = dist + " m"
+ }
+ return dist
+ }
+
+ function formatArrivalTime(sec)
+ {
+ var date = StatusBarService.currentDate
+ var secs = date.getUTCSeconds() + sec
+ date.setUTCSeconds(secs)
+ date = Qt.formatDateTime(date, "hh:mm")
+ return date
+ }
+}
+
diff --git a/CenterConsole/sysui/CenterItems/SearchInput.qml b/CenterConsole/sysui/CenterItems/SearchInput.qml
new file mode 100644
index 0000000..7a39bee
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/SearchInput.qml
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.VirtualKeyboard 2.1
+import QtQuick.VirtualKeyboard.Settings 2.1
+
+import utils 1.0
+import controls 1.0
+
+Item {
+ id: root
+ width: Style.screenWidth
+ property int panelHeight: panel.height
+ Rectangle {
+ id: searchInput
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: panel.top
+ anchors.bottomMargin: 10
+ anchors.leftMargin: 20
+ anchors.rightMargin: 20
+ radius: Style.buttonRadius
+ height: Style.searchInputHeight
+
+ TextInput {
+ id: textInput
+ width: parent.width
+ color: Style.colorBlack
+ focus: true
+ //hide cursor
+ cursorDelegate: Item {}
+ horizontalAlignment: TextInput.AlignHCenter
+ font.pixelSize: Style.fontSizeS
+ Keys.onReleased: {
+ if (event.key === Qt.Key_Return) {
+ root.mapState = "showRoute"
+ textInput.clear()
+ }
+ }
+
+ MouseArea {
+ id: focusMouseArea
+ anchors.fill: parent
+ onClicked: {
+ textInput.forceActiveFocus()
+ Qt.inputMethod.show()
+ }
+ }
+ }
+ Label {
+ id: previewText
+ z: 10
+ color: "#a0a1a2"
+ visible: !inputPanel.active
+ text: "Where would you like to go?"
+ font.pixelSize: Style.fontSizeM
+ anchors.centerIn: parent
+ }
+ }
+ Image {
+ id: closeButton
+ anchors.bottom: searchInput.top
+ anchors.right: searchInput.right
+ anchors.bottomMargin: Style.padding
+ source: Style.symbol("cancel")
+ visible: inputPanel.active
+ MouseArea {
+ anchors.fill: parent
+ onClicked: Qt.inputMethod.hide()
+ }
+ }
+
+ Rectangle {
+ id: panel
+ color: "#262a32"
+ opacity: 0.95
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: inputPanel.top
+ implicitHeight: childrenRect.height + 50
+ Row {
+ id: poiRow
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: Style.paddingXL
+ spacing: width / 7
+ MapPOI { poiText: "Charging stations"; poiIcon: "placeofinterest-charging" }
+ MapPOI { poiText: "Parking"; poiIcon: "placeofinterest-parking" }
+ MapPOI { poiText: "Coffee"; poiIcon: "placeofinterest-coffee" }
+ MapPOI { poiText: "Shopping"; poiIcon: "placeofinterest-shopping" }
+ }
+ Column {
+ anchors.top: poiRow.bottom
+ anchors.right: parent.right
+ anchors.left: parent.left
+ anchors.margins: 40
+ Label {
+ font.pixelSize: Style.fontSizeL
+ text: "SUGGESTED PLACES"
+ }
+
+ spacing: 30
+ Rectangle { width: parent.width; height: 2; color: "#61656C" }
+ SuggestedPlaces { image: "destination-airport" }
+ Rectangle { width: parent.width; height: 2; color:"#61656C" }
+ SuggestedPlaces { image: "destination-home" }
+ Rectangle { width: parent.width; height: 2; color: "#61656C" }
+ SuggestedPlaces { image: "destination-work" }
+ Rectangle { width: parent.width; height: 2; color: "#61656C" }
+ }
+ }
+
+ /* Handwriting input panel for full screen handwriting input.
+
+ This component is an optional add-on for the InputPanel component, that
+ is, its use does not affect the operation of the InputPanel component,
+ but it also can not be used as a standalone component.
+
+ The handwriting input panel is positioned to cover the entire area of
+ application. The panel itself is transparent, but once it is active the
+ user can draw handwriting on it.
+ */
+ HandwritingInputPanel {
+ z: 79
+ id: handwritingInputPanel
+ anchors.fill: parent
+ inputPanel: inputPanel
+ Rectangle {
+ z: -1
+ anchors.fill: parent
+ color: "black"
+ opacity: 0.10
+ }
+ }
+
+ /* Container area for the handwriting mode button.
+
+ Handwriting mode button can be moved freely within the container area.
+ In this example, a single click changes the handwriting mode and a
+ double-click changes the availability of the full screen handwriting input.
+ */
+ Item {
+ z: 89
+ visible: handwritingInputPanel.enabled && Qt.inputMethod.visible
+ anchors { left: parent.left; top: parent.top; right: parent.right; bottom: inputPanel.top; }
+ HandwritingModeButton {
+ id: handwritingModeButton
+ anchors.top: parent.top
+ anchors.right: parent.right
+ anchors.margins: 10
+ floating: true
+ flipable: true
+ width: 76
+ height: width
+ state: handwritingInputPanel.state
+ onPressed: handwritingInputPanel.active = !handwritingInputPanel.active
+ onDoubleClicked: handwritingInputPanel.available = !handwritingInputPanel.available
+ }
+ }
+
+ InputPanel {
+ id: inputPanel
+ anchors.left: parent.left
+ anchors.right: parent.right
+ visible: active
+
+ states: State {
+ name: "visible"
+ /* The visibility of the InputPanel can be bound to the Qt.inputMethod.visible property,
+ but then the handwriting input panel and the keyboard input panel can be visible
+ at the same time. Here the visibility is bound to InputPanel.active property instead,
+ which allows the handwriting panel to control the visibility when necessary.
+ */
+ when: inputPanel.active
+ PropertyChanges {
+ target: inputPanel
+ y: root.height - inputPanel.height - panel.height
+ }
+ }
+ transitions: Transition {
+ from: ""
+ to: "visible"
+ reversible: true
+ ParallelAnimation {
+ NumberAnimation {
+ properties: "y"
+ duration: 500
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ Component.onCompleted: {
+ VirtualKeyboardSettings.styleName = "automotive"
+ }
+ }
+
+}
diff --git a/CenterConsole/sysui/CenterItems/SuggestedPlaces.qml b/CenterConsole/sysui/CenterItems/SuggestedPlaces.qml
new file mode 100644
index 0000000..3eded9c
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/SuggestedPlaces.qml
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+import service.valuesource 1.0
+
+Item {
+ property string location: ValueSource.destination
+ property string address: "Ernst-Reuter-Platz 1-2"
+ property string image
+ width: Style.screenWidth
+ height: Style.cellHeight
+ Row {
+ id: suggestedPlace
+
+ spacing: Style.paddingXXL
+ Image{
+ id: icon
+ source: Style.symbol(image)
+ }
+ Column {
+ anchors.verticalCenter: icon.verticalCenter
+ Text{
+ text: location
+ font.pixelSize: Style.fontSizeL
+ color: Style.colorWhite
+ }
+ Text{
+ text: address
+ font.pixelSize: Style.fontSizeXS
+ color: "#8E9399"
+ }
+ }
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ root.mapState = "showRoute"
+ Qt.inputMethod.hide()
+ }
+ }
+}
diff --git a/CenterConsole/sysui/CenterItems/offlineRoute.txt b/CenterConsole/sysui/CenterItems/offlineRoute.txt
new file mode 100644
index 0000000..206b358
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/offlineRoute.txt
@@ -0,0 +1,272 @@
+[{"latitude": "52.5347", "longitude": "13.2934"},
+{"latitude": "52.5347", "longitude": "13.2934"},
+{"latitude": "52.5346", "longitude": "13.2933"},
+{"latitude": "52.5346", "longitude": "13.2932"},
+{"latitude": "52.5345", "longitude": "13.2932"},
+{"latitude": "52.5343", "longitude": "13.2932"},
+{"latitude": "52.5343", "longitude": "13.2932"},
+{"latitude": "52.5342", "longitude": "13.2932"},
+{"latitude": "52.5342", "longitude": "13.2933"},
+{"latitude": "52.5342", "longitude": "13.2933"},
+{"latitude": "52.5342", "longitude": "13.2933"},
+{"latitude": "52.5342", "longitude": "13.2933"},
+{"latitude": "52.5342", "longitude": "13.2933"},
+{"latitude": "52.5342", "longitude": "13.2934"},
+{"latitude": "52.5342", "longitude": "13.2934"},
+{"latitude": "52.5341", "longitude": "13.2934"},
+{"latitude": "52.5341", "longitude": "13.2934"},
+{"latitude": "52.534", "longitude": "13.2936"},
+{"latitude": "52.534", "longitude": "13.2936"},
+{"latitude": "52.534", "longitude": "13.2936"},
+{"latitude": "52.5339", "longitude": "13.2937"},
+{"latitude": "52.5339", "longitude": "13.2937"},
+{"latitude": "52.5339", "longitude": "13.2937"},
+{"latitude": "52.5337", "longitude": "13.2938"},
+{"latitude": "52.5337", "longitude": "13.2939"},
+{"latitude": "52.5336", "longitude": "13.2939"},
+{"latitude": "52.5335", "longitude": "13.294"},
+{"latitude": "52.5334", "longitude": "13.294"},
+{"latitude": "52.5332", "longitude": "13.2941"},
+{"latitude": "52.5331", "longitude": "13.2942"},
+{"latitude": "52.5328", "longitude": "13.2944"},
+{"latitude": "52.5327", "longitude": "13.2944"},
+{"latitude": "52.5324", "longitude": "13.2947"},
+{"latitude": "52.5323", "longitude": "13.2947"},
+{"latitude": "52.5322", "longitude": "13.2948"},
+{"latitude": "52.5319", "longitude": "13.295"},
+{"latitude": "52.5316", "longitude": "13.2952"},
+{"latitude": "52.5314", "longitude": "13.2953"},
+{"latitude": "52.5312", "longitude": "13.2954"},
+{"latitude": "52.531", "longitude": "13.2955"},
+{"latitude": "52.531", "longitude": "13.2955"},
+{"latitude": "52.5308", "longitude": "13.2955"},
+{"latitude": "52.5308", "longitude": "13.2956"},
+{"latitude": "52.5304", "longitude": "13.2957"},
+{"latitude": "52.53", "longitude": "13.2958"},
+{"latitude": "52.5299", "longitude": "13.2958"},
+{"latitude": "52.5299", "longitude": "13.2959"},
+{"latitude": "52.5296", "longitude": "13.296"},
+{"latitude": "52.5295", "longitude": "13.296"},
+{"latitude": "52.5294", "longitude": "13.2961"},
+{"latitude": "52.5293", "longitude": "13.2961"},
+{"latitude": "52.5292", "longitude": "13.2962"},
+{"latitude": "52.529", "longitude": "13.2964"},
+{"latitude": "52.529", "longitude": "13.2964"},
+{"latitude": "52.5289", "longitude": "13.2965"},
+{"latitude": "52.5289", "longitude": "13.2965"},
+{"latitude": "52.5288", "longitude": "13.2965"},
+{"latitude": "52.5287", "longitude": "13.2965"},
+{"latitude": "52.5285", "longitude": "13.2966"},
+{"latitude": "52.5277", "longitude": "13.2969"},
+{"latitude": "52.527", "longitude": "13.2971"},
+{"latitude": "52.5265", "longitude": "13.2972"},
+{"latitude": "52.5257", "longitude": "13.2974"},
+{"latitude": "52.5255", "longitude": "13.2975"},
+{"latitude": "52.5255", "longitude": "13.2975"},
+{"latitude": "52.525", "longitude": "13.2977"},
+{"latitude": "52.5249", "longitude": "13.2977"},
+{"latitude": "52.5247", "longitude": "13.2978"},
+{"latitude": "52.5246", "longitude": "13.2979"},
+{"latitude": "52.5246", "longitude": "13.2979"},
+{"latitude": "52.5245", "longitude": "13.2979"},
+{"latitude": "52.5243", "longitude": "13.2982"},
+{"latitude": "52.5242", "longitude": "13.2984"},
+{"latitude": "52.5236", "longitude": "13.2991"},
+{"latitude": "52.5233", "longitude": "13.2995"},
+{"latitude": "52.523", "longitude": "13.2999"},
+{"latitude": "52.5229", "longitude": "13.2999"},
+{"latitude": "52.5228", "longitude": "13.3001"},
+{"latitude": "52.5226", "longitude": "13.3003"},
+{"latitude": "52.5226", "longitude": "13.3004"},
+{"latitude": "52.5226", "longitude": "13.3004"},
+{"latitude": "52.5225", "longitude": "13.3004"},
+{"latitude": "52.5225", "longitude": "13.3004"},
+{"latitude": "52.5225", "longitude": "13.3004"},
+{"latitude": "52.5225", "longitude": "13.3004"},
+{"latitude": "52.5225", "longitude": "13.3004"},
+{"latitude": "52.5222", "longitude": "13.3003"},
+{"latitude": "52.5221", "longitude": "13.3003"},
+{"latitude": "52.5221", "longitude": "13.3003"},
+{"latitude": "52.5218", "longitude": "13.3"},
+{"latitude": "52.5217", "longitude": "13.2999"},
+{"latitude": "52.5217", "longitude": "13.2999"},
+{"latitude": "52.5217", "longitude": "13.2999"},
+{"latitude": "52.5214", "longitude": "13.2998"},
+{"latitude": "52.5214", "longitude": "13.2998"},
+{"latitude": "52.5213", "longitude": "13.2997"},
+{"latitude": "52.521", "longitude": "13.2995"},
+{"latitude": "52.5209", "longitude": "13.2994"},
+{"latitude": "52.5208", "longitude": "13.2994"},
+{"latitude": "52.5207", "longitude": "13.2994"},
+{"latitude": "52.5207", "longitude": "13.2994"},
+{"latitude": "52.5206", "longitude": "13.2994"},
+{"latitude": "52.5206", "longitude": "13.2994"},
+{"latitude": "52.5205", "longitude": "13.2994"},
+{"latitude": "52.5204", "longitude": "13.2994"},
+{"latitude": "52.5204", "longitude": "13.2994"},
+{"latitude": "52.5202", "longitude": "13.2994"},
+{"latitude": "52.5201", "longitude": "13.2994"},
+{"latitude": "52.5201", "longitude": "13.2994"},
+{"latitude": "52.5199", "longitude": "13.2994"},
+{"latitude": "52.5198", "longitude": "13.2995"},
+{"latitude": "52.5197", "longitude": "13.2995"},
+{"latitude": "52.5197", "longitude": "13.2995"},
+{"latitude": "52.5196", "longitude": "13.2995"},
+{"latitude": "52.5195", "longitude": "13.2995"},
+{"latitude": "52.5195", "longitude": "13.2996"},
+{"latitude": "52.5195", "longitude": "13.2997"},
+{"latitude": "52.5195", "longitude": "13.2998"},
+{"latitude": "52.5195", "longitude": "13.2998"},
+{"latitude": "52.5195", "longitude": "13.2999"},
+{"latitude": "52.5195", "longitude": "13.3"},
+{"latitude": "52.5194", "longitude": "13.3003"},
+{"latitude": "52.5193", "longitude": "13.3005"},
+{"latitude": "52.5191", "longitude": "13.3012"},
+{"latitude": "52.5187", "longitude": "13.3022"},
+{"latitude": "52.518", "longitude": "13.3044"},
+{"latitude": "52.5179", "longitude": "13.3048"},
+{"latitude": "52.5178", "longitude": "13.3052"},
+{"latitude": "52.5177", "longitude": "13.3053"},
+{"latitude": "52.5177", "longitude": "13.3056"},
+{"latitude": "52.5176", "longitude": "13.3057"},
+{"latitude": "52.5176", "longitude": "13.3058"},
+{"latitude": "52.5175", "longitude": "13.3059"},
+{"latitude": "52.5175", "longitude": "13.3062"},
+{"latitude": "52.5174", "longitude": "13.3064"},
+{"latitude": "52.5173", "longitude": "13.3067"},
+{"latitude": "52.5172", "longitude": "13.3071"},
+{"latitude": "52.5167", "longitude": "13.3088"},
+{"latitude": "52.5164", "longitude": "13.3095"},
+{"latitude": "52.5161", "longitude": "13.3105"},
+{"latitude": "52.5152", "longitude": "13.3134"},
+{"latitude": "52.5149", "longitude": "13.3143"},
+{"latitude": "52.5148", "longitude": "13.3146"},
+{"latitude": "52.5146", "longitude": "13.3151"},
+{"latitude": "52.5146", "longitude": "13.3153"},
+{"latitude": "52.5145", "longitude": "13.3157"},
+{"latitude": "52.5142", "longitude": "13.3165"},
+{"latitude": "52.5141", "longitude": "13.3168"},
+{"latitude": "52.514", "longitude": "13.3171"},
+{"latitude": "52.514", "longitude": "13.3172"},
+{"latitude": "52.5139", "longitude": "13.3173"},
+{"latitude": "52.5139", "longitude": "13.3174"},
+{"latitude": "52.5139", "longitude": "13.3175"},
+{"latitude": "52.5138", "longitude": "13.3177"},
+{"latitude": "52.5138", "longitude": "13.3179"},
+{"latitude": "52.5138", "longitude": "13.3181"},
+{"latitude": "52.5137", "longitude": "13.3184"},
+{"latitude": "52.5137", "longitude": "13.3186"},
+{"latitude": "52.5137", "longitude": "13.3188"},
+{"latitude": "52.5136", "longitude": "13.3191"},
+{"latitude": "52.5136", "longitude": "13.3193"},
+{"latitude": "52.5135", "longitude": "13.3199"},
+{"latitude": "52.5134", "longitude": "13.3202"},
+{"latitude": "52.5134", "longitude": "13.3203"},
+{"latitude": "52.5134", "longitude": "13.3204"},
+{"latitude": "52.5133", "longitude": "13.3205"},
+{"latitude": "52.5133", "longitude": "13.3205"},
+{"latitude": "52.5133", "longitude": "13.3206"},
+{"latitude": "52.5133", "longitude": "13.3207"},
+{"latitude": "52.5132", "longitude": "13.3208"},
+{"latitude": "52.5132", "longitude": "13.3208"},
+{"latitude": "52.5132", "longitude": "13.3208"},
+{"latitude": "52.5132", "longitude": "13.3208"},
+{"latitude": "52.5132", "longitude": "13.3209"},
+{"latitude": "52.5132", "longitude": "13.3209"},
+{"latitude": "52.5132", "longitude": "13.3209"},
+{"latitude": "52.5132", "longitude": "13.3209"},
+{"latitude": "52.5132", "longitude": "13.3209"},
+{"latitude": "52.5132", "longitude": "13.3209"},
+{"latitude": "52.5132", "longitude": "13.3209"},
+{"latitude": "52.5131", "longitude": "13.3209"},
+{"latitude": "52.5131", "longitude": "13.3209"},
+{"latitude": "52.5131", "longitude": "13.3209"},
+{"latitude": "52.5131", "longitude": "13.3209"},
+{"latitude": "52.5131", "longitude": "13.3209"},
+{"latitude": "52.5131", "longitude": "13.321"},
+{"latitude": "52.5131", "longitude": "13.321"},
+{"latitude": "52.5131", "longitude": "13.321"},
+{"latitude": "52.5131", "longitude": "13.321"},
+{"latitude": "52.513", "longitude": "13.321"},
+{"latitude": "52.5129", "longitude": "13.321"},
+{"latitude": "52.5129", "longitude": "13.321"},
+{"latitude": "52.5129", "longitude": "13.321"},
+{"latitude": "52.5129", "longitude": "13.321"},
+{"latitude": "52.5129", "longitude": "13.3209"},
+{"latitude": "52.5128", "longitude": "13.3209"},
+{"latitude": "52.5128", "longitude": "13.3209"},
+{"latitude": "52.5128", "longitude": "13.3209"},
+{"latitude": "52.5128", "longitude": "13.3209"},
+{"latitude": "52.5127", "longitude": "13.3209"},
+{"latitude": "52.5127", "longitude": "13.3209"},
+{"latitude": "52.5127", "longitude": "13.3209"},
+{"latitude": "52.5127", "longitude": "13.3209"},
+{"latitude": "52.5127", "longitude": "13.3209"},
+{"latitude": "52.5126", "longitude": "13.3209"},
+{"latitude": "52.5126", "longitude": "13.3208"},
+{"latitude": "52.5126", "longitude": "13.3208"},
+{"latitude": "52.5126", "longitude": "13.3208"},
+{"latitude": "52.5126", "longitude": "13.3209"},
+{"latitude": "52.5125", "longitude": "13.3209"},
+{"latitude": "52.5125", "longitude": "13.3209"},
+{"latitude": "52.5125", "longitude": "13.3209"},
+{"latitude": "52.5124", "longitude": "13.3209"},
+{"latitude": "52.5124", "longitude": "13.3209"},
+{"latitude": "52.5124", "longitude": "13.3209"},
+{"latitude": "52.5124", "longitude": "13.3209"},
+{"latitude": "52.5123", "longitude": "13.3209"},
+{"latitude": "52.5123", "longitude": "13.3209"},
+{"latitude": "52.5123", "longitude": "13.321"},
+{"latitude": "52.5123", "longitude": "13.321"},
+{"latitude": "52.5123", "longitude": "13.321"},
+{"latitude": "52.5123", "longitude": "13.321"},
+{"latitude": "52.5122", "longitude": "13.321"},
+{"latitude": "52.5122", "longitude": "13.321"},
+{"latitude": "52.5122", "longitude": "13.3211"},
+{"latitude": "52.5122", "longitude": "13.3211"},
+{"latitude": "52.5122", "longitude": "13.3211"},
+{"latitude": "52.5121", "longitude": "13.3211"},
+{"latitude": "52.5121", "longitude": "13.3212"},
+{"latitude": "52.5121", "longitude": "13.3212"},
+{"latitude": "52.5121", "longitude": "13.3213"},
+{"latitude": "52.5121", "longitude": "13.3213"},
+{"latitude": "52.5121", "longitude": "13.3213"},
+{"latitude": "52.5121", "longitude": "13.3214"},
+{"latitude": "52.5121", "longitude": "13.3214"},
+{"latitude": "52.5121", "longitude": "13.3215"},
+{"latitude": "52.512", "longitude": "13.3215"},
+{"latitude": "52.512", "longitude": "13.3215"},
+{"latitude": "52.512", "longitude": "13.3216"},
+{"latitude": "52.512", "longitude": "13.3216"},
+{"latitude": "52.512", "longitude": "13.3216"},
+{"latitude": "52.512", "longitude": "13.3217"},
+{"latitude": "52.512", "longitude": "13.3217"},
+{"latitude": "52.512", "longitude": "13.3218"},
+{"latitude": "52.512", "longitude": "13.3219"},
+{"latitude": "52.512", "longitude": "13.3219"},
+{"latitude": "52.512", "longitude": "13.322"},
+{"latitude": "52.512", "longitude": "13.322"},
+{"latitude": "52.512", "longitude": "13.322"},
+{"latitude": "52.512", "longitude": "13.3221"},
+{"latitude": "52.512", "longitude": "13.3222"},
+{"latitude": "52.5121", "longitude": "13.3222"},
+{"latitude": "52.5121", "longitude": "13.3223"},
+{"latitude": "52.5121", "longitude": "13.3223"},
+{"latitude": "52.5121", "longitude": "13.3224"},
+{"latitude": "52.5121", "longitude": "13.3224"},
+{"latitude": "52.5121", "longitude": "13.3225"},
+{"latitude": "52.5121", "longitude": "13.3225"},
+{"latitude": "52.5122", "longitude": "13.3226"},
+{"latitude": "52.5122", "longitude": "13.3226"},
+{"latitude": "52.5122", "longitude": "13.3226"},
+{"latitude": "52.5122", "longitude": "13.3227"},
+{"latitude": "52.5122", "longitude": "13.3227"},
+{"latitude": "52.5123", "longitude": "13.3228"},
+{"latitude": "52.5123", "longitude": "13.3228"},
+{"latitude": "52.5123", "longitude": "13.3228"},
+{"latitude": "52.5124", "longitude": "13.3228"},
+{"latitude": "52.5124", "longitude": "13.3228"},
+{"latitude": "52.5124", "longitude": "13.3228"},
+{"latitude": "52.5124", "longitude": "13.3229"},
+{"latitude": "52.5125", "longitude": "13.3229"},
+{"latitude": "52.5125", "longitude": "13.3229"}]
diff --git a/CenterConsole/sysui/CenterItems/route.txt b/CenterConsole/sysui/CenterItems/route.txt
new file mode 100644
index 0000000..0f08fd2
--- /dev/null
+++ b/CenterConsole/sysui/CenterItems/route.txt
@@ -0,0 +1,1016 @@
+$GPGGA,070953,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,070953,A,5232.08,N,1317.6,E,4.8,200.0,030308,11.2,W,A*39
+$GPGGA,070954,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,070954,A,5232.08,N,1317.6,E,12.6,200.0,030308,11.2,W,A*07
+$GPGGA,070955,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,070955,A,5232.08,N,1317.6,E,15.6,211.0,030308,11.2,W,A*01
+$GPGGA,070956,5232.08,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,070956,A,5232.08,N,1317.59,E,14.7,270.0,030308,11.2,W,A*3f
+$GPGGA,070957,5232.07,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,070957,A,5232.07,N,1317.59,E,23.6,180.0,030308,11.2,W,A*38
+$GPGGA,070958,5232.06,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,070958,A,5232.06,N,1317.59,E,28.2,180.0,030308,11.2,W,A*39
+$GPGGA,070959,5232.06,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,070959,A,5232.06,N,1317.59,E,8.6,180.0,030308,11.2,W,A*0e
+$GPGGA,071000,5232.05,N,1317.59,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071000,A,5232.05,N,1317.59,E,9.9,180.0,030308,11.2,W,A*07
+$GPGGA,071001,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,071001,A,5232.05,N,1317.6,E,9.8,89.0,030308,11.2,W,A*05
+$GPGGA,071002,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,071002,A,5232.05,N,1317.6,E,2.8,89.0,030308,11.2,W,A*0d
+$GPGGA,071003,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,071003,A,5232.05,N,1317.6,E,3.1,89.0,030308,11.2,W,A*04
+$GPGGA,071004,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,071004,A,5232.05,N,1317.6,E,2.8,89.0,030308,11.2,W,A*0b
+$GPGGA,071005,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,071005,A,5232.05,N,1317.6,E,3.6,89.0,030308,11.2,W,A*05
+$GPGGA,071006,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7d
+$GPRMC,071006,A,5232.05,N,1317.6,E,3.1,89.0,030308,11.2,W,A*01
+$GPGGA,071007,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,071007,A,5232.05,N,1317.6,E,1.2,89.0,030308,11.2,W,A*01
+$GPGGA,071008,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,071008,A,5232.05,N,1317.6,E,3.6,180.0,030308,11.2,W,A*30
+$GPGGA,071009,5232.05,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*72
+$GPRMC,071009,A,5232.05,N,1317.6,E,3.1,180.0,030308,11.2,W,A*36
+$GPGGA,071010,5232.04,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071010,A,5232.04,N,1317.62,E,33.8,129.0,030308,11.2,W,A*34
+$GPGGA,071011,5232.04,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071011,A,5232.04,N,1317.62,E,6.7,129.0,030308,11.2,W,A*0c
+$GPGGA,071012,5232.04,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071012,A,5232.04,N,1317.62,E,8.5,129.0,030308,11.2,W,A*03
+$GPGGA,071013,5232.03,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071013,A,5232.03,N,1317.62,E,7.7,148.0,030308,11.2,W,A*0f
+$GPGGA,071014,5232.03,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071014,A,5232.03,N,1317.62,E,9.8,148.0,030308,11.2,W,A*09
+$GPGGA,071015,5232.03,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071015,A,5232.03,N,1317.62,E,1.4,148.0,030308,11.2,W,A*0c
+$GPGGA,071016,5232.02,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071016,A,5232.02,N,1317.63,E,39.9,163.0,030308,11.2,W,A*30
+$GPGGA,071017,5232.02,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071017,A,5232.02,N,1317.63,E,11.5,89.0,030308,11.2,W,A*02
+$GPGGA,071018,5232.02,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071018,A,5232.02,N,1317.63,E,11.4,180.0,030308,11.2,W,A*34
+$GPGGA,071019,5232.01,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071019,A,5232.01,N,1317.64,E,21.3,148.0,030308,11.2,W,A*31
+$GPGGA,071020,5232,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*66
+$GPRMC,071020,A,5232,N,1317.64,E,29.5,180.0,030308,11.2,W,A*1e
+$GPGGA,071021,5231.99,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071021,A,5231.99,N,1317.65,E,38.6,163.0,030308,11.2,W,A*3d
+$GPGGA,071022,5231.99,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071022,A,5231.99,N,1317.65,E,39.9,148.0,030308,11.2,W,A*39
+$GPGGA,071023,5231.97,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071023,A,5231.97,N,1317.66,E,57.6,157.0,030308,11.2,W,A*3c
+$GPGGA,071024,5231.96,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071024,A,5231.96,N,1317.66,E,19.1,180.0,030308,11.2,W,A*3d
+$GPGGA,071025,5231.94,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071025,A,5231.94,N,1317.68,E,88.4,148.0,030308,11.2,W,A*39
+$GPGGA,071026,5231.94,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071026,A,5231.94,N,1317.68,E,4.9,180.0,030308,11.2,W,A*07
+$GPGGA,071027,5231.93,N,1317.69,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071027,A,5231.93,N,1317.69,E,25.2,148.0,030308,11.2,W,A*3c
+$GPGGA,071028,5231.91,N,1317.7,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,071028,A,5231.91,N,1317.7,E,82.2,157.0,030308,11.2,W,A*0a
+$GPGGA,071029,5231.9,N,1317.71,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,071029,A,5231.9,N,1317.71,E,67.1,157.0,030308,11.2,W,A*03
+$GPGGA,071030,5231.88,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071030,A,5231.88,N,1317.72,E,41.0,163.0,030308,11.2,W,A*33
+$GPGGA,071031,5231.87,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071031,A,5231.87,N,1317.72,E,43.3,162.0,030308,11.2,W,A*3d
+$GPGGA,071032,5231.86,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071032,A,5231.86,N,1317.73,E,46.9,163.0,030308,11.2,W,A*30
+$GPGGA,071033,5231.86,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071033,A,5231.86,N,1317.73,E,6.7,163.0,030308,11.2,W,A*0b
+$GPGGA,071034,5231.85,N,1317.73,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071034,A,5231.85,N,1317.73,E,30.4,180.0,030308,11.2,W,A*34
+$GPGGA,071035,5231.85,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071035,A,5231.85,N,1317.74,E,2.8,89.0,030308,11.2,W,A*37
+$GPGGA,071036,5231.82,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071036,A,5231.82,N,1317.74,E,92.4,171.0,030308,11.2,W,A*30
+$GPGGA,071037,5231.8,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,071037,A,5231.8,N,1317.75,E,84.6,171.0,030308,11.2,W,A*07
+$GPGGA,071038,5231.79,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071038,A,5231.79,N,1317.75,E,17.8,180.0,030308,11.2,W,A*34
+$GPGGA,071039,5231.79,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071039,A,5231.79,N,1317.75,E,19.4,89.0,030308,11.2,W,A*0f
+$GPGGA,071040,5231.78,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071040,A,5231.78,N,1317.76,E,60.1,168.0,030308,11.2,W,A*36
+$GPGGA,071041,5231.77,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071041,A,5231.77,N,1317.76,E,13.4,180.0,030308,11.2,W,A*3f
+$GPGGA,071042,5231.76,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071042,A,5231.76,N,1317.77,E,33.1,148.0,030308,11.2,W,A*3f
+$GPGGA,071043,5231.76,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071043,A,5231.76,N,1317.77,E,19.1,180.0,030308,11.2,W,A*32
+$GPGGA,071044,5231.75,N,1317.77,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071044,A,5231.75,N,1317.77,E,23.9,148.0,030308,11.2,W,A*33
+$GPGGA,071045,5231.74,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071045,A,5231.74,N,1317.78,E,47.6,148.0,030308,11.2,W,A*31
+$GPGGA,071046,5231.74,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071046,A,5231.74,N,1317.78,E,12.6,148.0,030308,11.2,W,A*32
+$GPGGA,071047,5231.73,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071047,A,5231.73,N,1317.79,E,11.5,148.0,030308,11.2,W,A*35
+$GPGGA,071048,5231.73,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071048,A,5231.73,N,1317.79,E,14.2,148.0,030308,11.2,W,A*38
+$GPGGA,071049,5231.73,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071049,A,5231.73,N,1317.79,E,11.0,180.0,030308,11.2,W,A*3a
+$GPGGA,071050,5231.72,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071050,A,5231.72,N,1317.79,E,20.2,180.0,030308,11.2,W,A*33
+$GPGGA,071051,5231.71,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,071051,A,5231.71,N,1317.8,E,50.4,163.0,030308,11.2,W,A*0b
+$GPGGA,071052,5231.66,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071052,A,5231.66,N,1317.81,E,178.1,167.0,030308,11.2,W,A*05
+$GPGGA,071053,5231.62,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071053,A,5231.62,N,1317.83,E,150.3,170.0,030308,11.2,W,A*0c
+$GPGGA,071054,5231.59,N,1317.83,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071054,A,5231.59,N,1317.83,E,107.5,173.0,030308,11.2,W,A*04
+$GPGGA,071055,5231.54,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071055,A,5231.54,N,1317.84,E,164.9,171.0,030308,11.2,W,A*04
+$GPGGA,071056,5231.53,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071056,A,5231.53,N,1317.85,E,46.1,163.0,030308,11.2,W,A*3b
+$GPGGA,071057,5231.53,N,1317.85,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071057,A,5231.53,N,1317.85,E,17.5,163.0,030308,11.2,W,A*3a
+$GPGGA,071058,5231.5,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*7d
+$GPRMC,071058,A,5231.5,N,1317.86,E,96.5,166.0,030308,11.2,W,A*09
+$GPGGA,071059,5231.49,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071059,A,5231.49,N,1317.86,E,18.1,180.0,030308,11.2,W,A*3a
+$GPGGA,071100,5231.48,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071100,A,5231.48,N,1317.87,E,50.0,162.0,030308,11.2,W,A*36
+$GPGGA,071101,5231.48,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071101,A,5231.48,N,1317.87,E,21.1,148.0,030308,11.2,W,A*38
+$GPGGA,071102,5231.48,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071102,A,5231.48,N,1317.87,E,12.2,148.0,030308,11.2,W,A*38
+$GPGGA,071103,5231.47,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071103,A,5231.47,N,1317.87,E,16.2,180.0,030308,11.2,W,A*36
+$GPGGA,071104,5231.46,N,1317.89,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071104,A,5231.46,N,1317.89,E,64.4,137.0,030308,11.2,W,A*31
+$GPGGA,071105,5231.45,N,1317.9,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,071105,A,5231.45,N,1317.9,E,21.7,129.0,030308,11.2,W,A*06
+$GPGGA,071106,5231.42,N,1317.95,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071106,A,5231.42,N,1317.95,E,155.6,144.0,030308,11.2,W,A*0f
+$GPGGA,071107,5231.4,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,071107,A,5231.4,N,1317.97,E,89.6,141.0,030308,11.2,W,A*0b
+$GPGGA,071108,5231.38,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071108,A,5231.38,N,1317.99,E,91.1,141.0,030308,11.2,W,A*3b
+$GPGGA,071109,5231.37,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071109,A,5231.37,N,1317.99,E,11.3,180.0,030308,11.2,W,A*32
+$GPGGA,071110,5231.37,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071110,A,5231.37,N,1318.01,E,33.2,129.0,030308,11.2,W,A*36
+$GPGGA,071111,5231.36,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071111,A,5231.36,N,1318.02,E,45.1,149.0,030308,11.2,W,A*31
+$GPGGA,071112,5231.36,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071112,A,5231.36,N,1318.02,E,10.5,89.0,030308,11.2,W,A*0b
+$GPGGA,071113,5231.36,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071113,A,5231.36,N,1318.02,E,5.8,89.0,030308,11.2,W,A*33
+$GPGGA,071114,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071114,A,5231.35,N,1318.02,E,9.8,180.0,030308,11.2,W,A*03
+$GPGGA,071115,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071115,A,5231.35,N,1318.02,E,0,180.0,030308,11.2,W,A*1d
+$GPGGA,071116,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071116,A,5231.35,N,1318.02,E,6.6,180.0,030308,11.2,W,A*00
+$GPGGA,071117,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071117,A,5231.35,N,1318.02,E,4.3,180.0,030308,11.2,W,A*06
+$GPGGA,071118,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071118,A,5231.35,N,1318.02,E,6.6,180.0,030308,11.2,W,A*0e
+$GPGGA,071119,5231.33,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071119,A,5231.33,N,1318.02,E,53.6,191.0,030308,11.2,W,A*39
+$GPGGA,071120,5231.33,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071120,A,5231.33,N,1318.02,E,28.0,180.0,030308,11.2,W,A*39
+$GPGGA,071121,5231.33,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071121,A,5231.33,N,1318.02,E,1.7,180.0,030308,11.2,W,A*04
+$GPGGA,071122,5231.31,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*69
+$GPRMC,071122,A,5231.31,N,1318,E,77.5,211.0,030308,11.2,W,A*11
+$GPGGA,071123,5231.3,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,071123,A,5231.3,N,1317.99,E,15.0,211.0,030308,11.2,W,A*01
+$GPGGA,071124,5231.3,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,071124,A,5231.3,N,1317.99,E,7.7,211.0,030308,11.2,W,A*32
+$GPGGA,071125,5231.3,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,071125,A,5231.3,N,1317.99,E,4.9,211.0,030308,11.2,W,A*3e
+$GPGGA,071126,5231.28,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071126,A,5231.28,N,1317.99,E,63.4,191.0,030308,11.2,W,A*33
+$GPGGA,071127,5231.28,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071127,A,5231.28,N,1317.99,E,nan,191.0,030308,11.2,W,A*4c
+$GPGGA,071128,5231.28,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071128,A,5231.28,N,1317.98,E,29.6,211.0,030308,11.2,W,A*3b
+$GPGGA,071129,5231.26,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071129,A,5231.26,N,1317.97,E,49.0,201.0,030308,11.2,W,A*3a
+$GPGGA,071130,5231.25,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071130,A,5231.25,N,1317.96,E,35.1,211.0,030308,11.2,W,A*3b
+$GPGGA,071131,5231.25,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071131,A,5231.25,N,1317.96,E,15.4,180.0,030308,11.2,W,A*36
+$GPGGA,071132,5231.24,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071132,A,5231.24,N,1317.96,E,15.9,180.0,030308,11.2,W,A*39
+$GPGGA,071133,5231.24,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071133,A,5231.24,N,1317.96,E,19.2,180.0,030308,11.2,W,A*3f
+$GPGGA,071134,5231.24,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071134,A,5231.24,N,1317.96,E,9.1,180.0,030308,11.2,W,A*0a
+$GPGGA,071135,5231.24,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071135,A,5231.24,N,1317.96,E,5.8,180.0,030308,11.2,W,A*0e
+$GPGGA,071136,5231.23,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071136,A,5231.23,N,1317.96,E,19.9,180.0,030308,11.2,W,A*36
+$GPGGA,071137,5231.22,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071137,A,5231.22,N,1317.96,E,17.4,180.0,030308,11.2,W,A*35
+$GPGGA,071138,5231.22,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071138,A,5231.22,N,1317.96,E,13.2,180.0,030308,11.2,W,A*38
+$GPGGA,071139,5231.21,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071139,A,5231.21,N,1317.96,E,29.7,180.0,030308,11.2,W,A*36
+$GPGGA,071140,5231.21,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071140,A,5231.21,N,1317.96,E,15.7,180.0,030308,11.2,W,A*37
+$GPGGA,071141,5231.21,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071141,A,5231.21,N,1317.96,E,19.0,180.0,030308,11.2,W,A*3d
+$GPGGA,071142,5231.19,N,1317.96,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071142,A,5231.19,N,1317.96,E,45.7,180.0,030308,11.2,W,A*3b
+$GPGGA,071143,5231.19,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071143,A,5231.19,N,1317.97,E,20.0,149.0,030308,11.2,W,A*3a
+$GPGGA,071144,5231.18,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071144,A,5231.18,N,1317.97,E,17.5,180.0,030308,11.2,W,A*38
+$GPGGA,071145,5231.18,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071145,A,5231.18,N,1317.97,E,0,180.0,030308,11.2,W,A*14
+$GPGGA,071146,5231.18,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071146,A,5231.18,N,1317.97,E,17.8,180.0,030308,11.2,W,A*37
+$GPGGA,071147,5231.17,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071147,A,5231.17,N,1317.97,E,20.0,180.0,030308,11.2,W,A*35
+$GPGGA,071148,5231.17,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071148,A,5231.17,N,1317.98,E,9.3,89.0,030308,11.2,W,A*35
+$GPGGA,071149,5231.17,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071149,A,5231.17,N,1317.98,E,11.9,89.0,030308,11.2,W,A*07
+$GPGGA,071150,5231.17,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071150,A,5231.17,N,1317.99,E,6.7,89.0,030308,11.2,W,A*36
+$GPGGA,071151,5231.17,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071151,A,5231.17,N,1317.99,E,10.8,89.0,030308,11.2,W,A*0f
+$GPGGA,071152,5231.17,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071152,A,5231.17,N,1317.99,E,8.0,89.0,030308,11.2,W,A*3d
+$GPGGA,071153,5231.17,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*6b
+$GPRMC,071153,A,5231.17,N,1318,E,12.4,89.0,030308,11.2,W,A*22
+$GPGGA,071154,5231.16,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071154,A,5231.16,N,1318.02,E,44.2,118.0,030308,11.2,W,A*34
+$GPGGA,071155,5231.16,N,1318.03,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071155,A,5231.16,N,1318.03,E,39.5,130.0,030308,11.2,W,A*33
+$GPGGA,071156,5231.15,N,1318.07,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071156,A,5231.15,N,1318.07,E,101.2,114.0,030308,11.2,W,A*0c
+$GPGGA,071157,5231.12,N,1318.13,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071157,A,5231.12,N,1318.13,E,152.2,123.0,030308,11.2,W,A*0d
+$GPGGA,071158,5231.08,N,1318.26,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071158,A,5231.08,N,1318.26,E,326.0,117.0,030308,11.2,W,A*0b
+$GPGGA,071159,5231.07,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071159,A,5231.07,N,1318.29,E,59.8,112.0,030308,11.2,W,A*3c
+$GPGGA,071200,5231.07,N,1318.31,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071200,A,5231.07,N,1318.31,E,58.5,112.0,030308,11.2,W,A*36
+$GPGGA,071201,5231.06,N,1318.32,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071201,A,5231.06,N,1318.32,E,13.5,148.0,030308,11.2,W,A*35
+$GPGGA,071202,5231.06,N,1318.34,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071202,A,5231.06,N,1318.34,E,40.7,89.0,030308,11.2,W,A*08
+$GPGGA,071203,5231.06,N,1318.34,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071203,A,5231.06,N,1318.34,E,21.4,148.0,030308,11.2,W,A*31
+$GPGGA,071204,5231.06,N,1318.35,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071204,A,5231.06,N,1318.35,E,6.7,89.0,030308,11.2,W,A*3d
+$GPGGA,071205,5231.05,N,1318.35,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071205,A,5231.05,N,1318.35,E,24.8,148.0,030308,11.2,W,A*3c
+$GPGGA,071206,5231.05,N,1318.37,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071206,A,5231.05,N,1318.37,E,31.5,89.0,030308,11.2,W,A*08
+$GPGGA,071207,5231.04,N,1318.38,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071207,A,5231.04,N,1318.38,E,44.1,130.0,030308,11.2,W,A*32
+$GPGGA,071208,5231.04,N,1318.4,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,071208,A,5231.04,N,1318.4,E,33.0,118.0,030308,11.2,W,A*09
+$GPGGA,071209,5231.03,N,1318.43,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071209,A,5231.03,N,1318.43,E,56.3,112.0,030308,11.2,W,A*36
+$GPGGA,071210,5231,N,1318.53,E,1,07,1.3,50.6,M,39.2,M,,*6f
+$GPRMC,071210,A,5231,N,1318.53,E,252.6,115.0,030308,11.2,W,A*26
+$GPGGA,071211,5230.98,N,1318.57,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071211,A,5230.98,N,1318.57,E,102.4,125.0,030308,11.2,W,A*0a
+$GPGGA,071212,5230.97,N,1318.63,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071212,A,5230.97,N,1318.63,E,154.6,116.0,030308,11.2,W,A*00
+$GPGGA,071213,5230.91,N,1318.8,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,071213,A,5230.91,N,1318.8,E,388.8,117.0,030308,11.2,W,A*36
+$GPGGA,071214,5230.89,N,1318.86,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071214,A,5230.89,N,1318.86,E,120.5,118.0,030308,11.2,W,A*0c
+$GPGGA,071215,5230.89,N,1318.88,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071215,A,5230.89,N,1318.88,E,54.3,118.0,030308,11.2,W,A*37
+$GPGGA,071216,5230.88,N,1318.91,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071216,A,5230.88,N,1318.91,E,76.4,123.0,030308,11.2,W,A*32
+$GPGGA,071217,5230.88,N,1318.92,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071217,A,5230.88,N,1318.92,E,21.8,89.0,030308,11.2,W,A*0f
+$GPGGA,071218,5230.87,N,1318.94,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071218,A,5230.87,N,1318.94,E,59.6,112.0,030308,11.2,W,A*3b
+$GPGGA,071219,5230.85,N,1318.99,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071219,A,5230.85,N,1318.99,E,126.3,121.0,030308,11.2,W,A*09
+$GPGGA,071220,5230.85,N,1319.01,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071220,A,5230.85,N,1319.01,E,41.5,118.0,030308,11.2,W,A*3f
+$GPGGA,071221,5230.84,N,1319.03,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071221,A,5230.84,N,1319.03,E,37.2,118.0,030308,11.2,W,A*3b
+$GPGGA,071222,5230.84,N,1319.03,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071222,A,5230.84,N,1319.03,E,18.2,89.0,030308,11.2,W,A*0c
+$GPGGA,071223,5230.83,N,1319.04,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071223,A,5230.83,N,1319.04,E,21.4,148.0,030308,11.2,W,A*3d
+$GPGGA,071224,5230.83,N,1319.04,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071224,A,5230.83,N,1319.04,E,11.7,89.0,030308,11.2,W,A*06
+$GPGGA,071225,5230.83,N,1319.05,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071225,A,5230.83,N,1319.05,E,13.8,89.0,030308,11.2,W,A*0b
+$GPGGA,071226,5230.83,N,1319.06,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071226,A,5230.83,N,1319.06,E,30.9,129.0,030308,11.2,W,A*30
+$GPGGA,071227,5230.83,N,1319.07,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071227,A,5230.83,N,1319.07,E,23.3,89.0,030308,11.2,W,A*03
+$GPGGA,071228,5230.83,N,1319.09,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071228,A,5230.83,N,1319.09,E,24.6,89.0,030308,11.2,W,A*00
+$GPGGA,071229,5230.82,N,1319.1,E,1,07,1.3,50.6,M,39.2,M,,*76
+$GPRMC,071229,A,5230.82,N,1319.1,E,44.8,119.0,030308,11.2,W,A*08
+$GPGGA,071230,5230.82,N,1319.12,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071230,A,5230.82,N,1319.12,E,25.8,89.0,030308,11.2,W,A*0d
+$GPGGA,071231,5230.82,N,1319.13,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071231,A,5230.82,N,1319.13,E,21.5,89.0,030308,11.2,W,A*04
+$GPGGA,071232,5230.82,N,1319.15,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071232,A,5230.82,N,1319.15,E,48.5,118.0,030308,11.2,W,A*37
+$GPGGA,071233,5230.82,N,1319.16,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071233,A,5230.82,N,1319.16,E,22.7,89.0,030308,11.2,W,A*02
+$GPGGA,071234,5230.81,N,1319.19,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071234,A,5230.81,N,1319.19,E,85.1,105.0,030308,11.2,W,A*37
+$GPGGA,071235,5230.8,N,1319.21,E,1,07,1.3,50.6,M,39.2,M,,*7b
+$GPRMC,071235,A,5230.8,N,1319.21,E,38.8,118.0,030308,11.2,W,A*0f
+$GPGGA,071236,5230.8,N,1319.22,E,1,07,1.3,50.6,M,39.2,M,,*7b
+$GPRMC,071236,A,5230.8,N,1319.22,E,15.9,89.0,030308,11.2,W,A*38
+$GPGGA,071237,5230.8,N,1319.22,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,071237,A,5230.8,N,1319.22,E,14.4,89.0,030308,11.2,W,A*35
+$GPGGA,071238,5230.8,N,1319.23,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,071238,A,5230.8,N,1319.23,E,11.7,148.0,030308,11.2,W,A*01
+$GPGGA,071239,5230.8,N,1319.23,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,071239,A,5230.8,N,1319.23,E,10.2,148.0,030308,11.2,W,A*04
+$GPGGA,071240,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,071240,A,5230.8,N,1319.24,E,13.5,89.0,030308,11.2,W,A*35
+$GPGGA,071241,5230.8,N,1319.24,E,1,07,1.3,50.6,M,39.2,M,,*7d
+$GPRMC,071241,A,5230.8,N,1319.24,E,10.1,89.0,030308,11.2,W,A*33
+$GPGGA,071242,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071242,A,5230.79,N,1319.25,E,12.4,149.0,030308,11.2,W,A*3d
+$GPGGA,071243,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071243,A,5230.79,N,1319.25,E,2.6,149.0,030308,11.2,W,A*0f
+$GPGGA,071244,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071244,A,5230.79,N,1319.25,E,3.1,149.0,030308,11.2,W,A*0e
+$GPGGA,071245,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071245,A,5230.79,N,1319.25,E,3.6,149.0,030308,11.2,W,A*08
+$GPGGA,071246,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071246,A,5230.79,N,1319.25,E,2.8,89.0,030308,11.2,W,A*39
+$GPGGA,071247,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071247,A,5230.79,N,1319.25,E,2.6,89.0,030308,11.2,W,A*36
+$GPGGA,071248,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071248,A,5230.79,N,1319.25,E,2.1,89.0,030308,11.2,W,A*3e
+$GPGGA,071249,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071249,A,5230.79,N,1319.25,E,2.5,89.0,030308,11.2,W,A*3b
+$GPGGA,071250,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071250,A,5230.79,N,1319.25,E,1.4,89.0,030308,11.2,W,A*31
+$GPGGA,071251,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071251,A,5230.79,N,1319.25,E,2.8,89.0,030308,11.2,W,A*3f
+$GPGGA,071252,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071252,A,5230.79,N,1319.25,E,2.2,89.0,030308,11.2,W,A*36
+$GPGGA,071253,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071253,A,5230.79,N,1319.25,E,2.8,180.0,030308,11.2,W,A*05
+$GPGGA,071254,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071254,A,5230.79,N,1319.25,E,2.1,180.0,030308,11.2,W,A*0b
+$GPGGA,071255,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071255,A,5230.79,N,1319.25,E,2.8,180.0,030308,11.2,W,A*03
+$GPGGA,071256,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071256,A,5230.79,N,1319.25,E,2.5,180.0,030308,11.2,W,A*0d
+$GPGGA,071257,5230.79,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071257,A,5230.79,N,1319.25,E,4.3,180.0,030308,11.2,W,A*0c
+$GPGGA,071258,5230.79,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071258,A,5230.79,N,1319.26,E,2.8,89.0,030308,11.2,W,A*35
+$GPGGA,071259,5230.79,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071259,A,5230.79,N,1319.26,E,1.7,89.0,030308,11.2,W,A*38
+$GPGGA,071300,5230.79,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071300,A,5230.79,N,1319.26,E,2.8,89.0,030308,11.2,W,A*39
+$GPGGA,071301,5230.79,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071301,A,5230.79,N,1319.26,E,1.7,89.0,030308,11.2,W,A*34
+$GPGGA,071302,5230.78,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071302,A,5230.78,N,1319.26,E,5.1,180.0,030308,11.2,W,A*0c
+$GPGGA,071303,5230.77,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071303,A,5230.77,N,1319.26,E,21.6,180.0,030308,11.2,W,A*33
+$GPGGA,071304,5230.77,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071304,A,5230.77,N,1319.26,E,0,180.0,030308,11.2,W,A*1f
+$GPGGA,071305,5230.77,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071305,A,5230.77,N,1319.26,E,4.9,180.0,030308,11.2,W,A*0d
+$GPGGA,071306,5230.77,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071306,A,5230.77,N,1319.26,E,7.1,180.0,030308,11.2,W,A*05
+$GPGGA,071307,5230.77,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071307,A,5230.77,N,1319.25,E,4.9,270.0,030308,11.2,W,A*00
+$GPGGA,071308,5230.77,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071308,A,5230.77,N,1319.25,E,7.1,180.0,030308,11.2,W,A*08
+$GPGGA,071309,5230.77,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071309,A,5230.77,N,1319.25,E,4.3,180.0,030308,11.2,W,A*08
+$GPGGA,071310,5230.77,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071310,A,5230.77,N,1319.25,E,7.1,180.0,030308,11.2,W,A*01
+$GPGGA,071311,5230.77,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071311,A,5230.77,N,1319.25,E,4.3,180.0,030308,11.2,W,A*01
+$GPGGA,071312,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071312,A,5230.76,N,1319.25,E,6.7,180.0,030308,11.2,W,A*05
+$GPGGA,071313,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071313,A,5230.76,N,1319.25,E,5.1,180.0,030308,11.2,W,A*01
+$GPGGA,071314,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071314,A,5230.76,N,1319.25,E,4.1,180.0,030308,11.2,W,A*07
+$GPGGA,071315,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071315,A,5230.76,N,1319.25,E,4.3,180.0,030308,11.2,W,A*04
+$GPGGA,071316,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071316,A,5230.76,N,1319.25,E,4.1,180.0,030308,11.2,W,A*05
+$GPGGA,071317,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071317,A,5230.76,N,1319.25,E,2.5,180.0,030308,11.2,W,A*06
+$GPGGA,071318,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071318,A,5230.76,N,1319.25,E,4.3,270.0,030308,11.2,W,A*05
+$GPGGA,071319,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071319,A,5230.76,N,1319.25,E,4.1,270.0,030308,11.2,W,A*06
+$GPGGA,071320,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071320,A,5230.76,N,1319.25,E,5.0,270.0,030308,11.2,W,A*0c
+$GPGGA,071321,5230.76,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071321,A,5230.76,N,1319.25,E,5.9,89.0,030308,11.2,W,A*30
+$GPGGA,071322,5230.75,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071322,A,5230.75,N,1319.25,E,6.6,180.0,030308,11.2,W,A*04
+$GPGGA,071323,5230.75,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071323,A,5230.75,N,1319.25,E,6.7,180.0,030308,11.2,W,A*04
+$GPGGA,071324,5230.75,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071324,A,5230.75,N,1319.25,E,6.7,180.0,030308,11.2,W,A*03
+$GPGGA,071325,5230.74,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071325,A,5230.74,N,1319.25,E,6.7,180.0,030308,11.2,W,A*03
+$GPGGA,071326,5230.74,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071326,A,5230.74,N,1319.25,E,6.8,180.0,030308,11.2,W,A*0f
+$GPGGA,071327,5230.74,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071327,A,5230.74,N,1319.25,E,7.1,180.0,030308,11.2,W,A*06
+$GPGGA,071328,5230.74,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071328,A,5230.74,N,1319.25,E,4.3,180.0,030308,11.2,W,A*08
+$GPGGA,071329,5230.74,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071329,A,5230.74,N,1319.25,E,7.1,180.0,030308,11.2,W,A*08
+$GPGGA,071330,5230.74,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071330,A,5230.74,N,1319.25,E,2.1,180.0,030308,11.2,W,A*05
+$GPGGA,071331,5230.74,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071331,A,5230.74,N,1319.26,E,5.6,89.0,030308,11.2,W,A*3f
+$GPGGA,071332,5230.74,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071332,A,5230.74,N,1319.26,E,2.1,89.0,030308,11.2,W,A*3c
+$GPGGA,071333,5230.74,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071333,A,5230.74,N,1319.26,E,4.9,89.0,030308,11.2,W,A*33
+$GPGGA,071334,5230.74,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071334,A,5230.74,N,1319.26,E,2.8,89.0,030308,11.2,W,A*33
+$GPGGA,071335,5230.73,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071335,A,5230.73,N,1319.26,E,4.9,180.0,030308,11.2,W,A*0a
+$GPGGA,071336,5230.73,N,1319.26,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071336,A,5230.73,N,1319.26,E,2.8,180.0,030308,11.2,W,A*0e
+$GPGGA,071337,5230.73,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071337,A,5230.73,N,1319.27,E,5.7,89.0,030308,11.2,W,A*3e
+$GPGGA,071338,5230.73,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071338,A,5230.73,N,1319.27,E,5.8,89.0,030308,11.2,W,A*3e
+$GPGGA,071339,5230.73,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071339,A,5230.73,N,1319.27,E,6.3,89.0,030308,11.2,W,A*37
+$GPGGA,071340,5230.73,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071340,A,5230.73,N,1319.27,E,4.9,180.0,030308,11.2,W,A*09
+$GPGGA,071341,5230.73,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071341,A,5230.73,N,1319.27,E,4.7,89.0,030308,11.2,W,A*3e
+$GPGGA,071342,5230.73,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071342,A,5230.73,N,1319.27,E,6.7,89.0,030308,11.2,W,A*3f
+$GPGGA,071343,5230.73,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071343,A,5230.73,N,1319.28,E,5.5,89.0,030308,11.2,W,A*30
+$GPGGA,071344,5230.73,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071344,A,5230.73,N,1319.28,E,7.1,89.0,030308,11.2,W,A*31
+$GPGGA,071345,5230.73,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071345,A,5230.73,N,1319.28,E,5.5,89.0,030308,11.2,W,A*36
+$GPGGA,071346,5230.73,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071346,A,5230.73,N,1319.28,E,7.2,89.0,030308,11.2,W,A*30
+$GPGGA,071347,5230.73,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071347,A,5230.73,N,1319.28,E,4.0,89.0,030308,11.2,W,A*30
+$GPGGA,071348,5230.73,N,1319.29,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071348,A,5230.73,N,1319.29,E,5.5,89.0,030308,11.2,W,A*3a
+$GPGGA,071349,5230.72,N,1319.29,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071349,A,5230.72,N,1319.29,E,8.3,180.0,030308,11.2,W,A*09
+$GPGGA,071350,5230.72,N,1319.29,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071350,A,5230.72,N,1319.29,E,nan,180.0,030308,11.2,W,A*45
+$GPGGA,071351,5230.72,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,071351,A,5230.72,N,1319.3,E,6.7,89.0,030308,11.2,W,A*0a
+$GPGGA,071352,5230.72,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*76
+$GPRMC,071352,A,5230.72,N,1319.3,E,5.8,89.0,030308,11.2,W,A*05
+$GPGGA,071353,5230.72,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,071353,A,5230.72,N,1319.3,E,5.3,89.0,030308,11.2,W,A*0f
+$GPGGA,071354,5230.72,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,071354,A,5230.72,N,1319.3,E,7.0,89.0,030308,11.2,W,A*09
+$GPGGA,071355,5230.72,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,071355,A,5230.72,N,1319.3,E,6.7,89.0,030308,11.2,W,A*0e
+$GPGGA,071356,5230.72,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071356,A,5230.72,N,1319.31,E,6.5,89.0,030308,11.2,W,A*3e
+$GPGGA,071357,5230.72,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071357,A,5230.72,N,1319.31,E,9.3,89.0,030308,11.2,W,A*36
+$GPGGA,071358,5230.72,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071358,A,5230.72,N,1319.31,E,6.5,89.0,030308,11.2,W,A*30
+$GPGGA,071359,5230.72,N,1319.32,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071359,A,5230.72,N,1319.32,E,6.7,89.0,030308,11.2,W,A*30
+$GPGGA,071400,5230.72,N,1319.32,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071400,A,5230.72,N,1319.32,E,5.2,89.0,030308,11.2,W,A*3d
+$GPGGA,071401,5230.72,N,1319.32,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071401,A,5230.72,N,1319.32,E,5.8,89.0,030308,11.2,W,A*36
+$GPGGA,071402,5230.72,N,1319.33,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071402,A,5230.72,N,1319.33,E,6.7,89.0,030308,11.2,W,A*38
+$GPGGA,071403,5230.72,N,1319.33,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071403,A,5230.72,N,1319.33,E,8.3,89.0,030308,11.2,W,A*33
+$GPGGA,071404,5230.73,N,1319.33,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071404,A,5230.73,N,1319.33,E,10.1,89.0,030308,11.2,W,A*0e
+$GPGGA,071405,5230.73,N,1319.34,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071405,A,5230.73,N,1319.34,E,8.1,89.0,030308,11.2,W,A*31
+$GPGGA,071406,5230.73,N,1319.34,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071406,A,5230.73,N,1319.34,E,8.3,89.0,030308,11.2,W,A*30
+$GPGGA,071407,5230.73,N,1319.34,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071407,A,5230.73,N,1319.34,E,6.7,89.0,030308,11.2,W,A*3b
+$GPGGA,071408,5230.73,N,1319.34,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071408,A,5230.73,N,1319.34,E,9.3,89.0,030308,11.2,W,A*3f
+$GPGGA,071409,5230.73,N,1319.35,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071409,A,5230.73,N,1319.35,E,5.5,89.0,030308,11.2,W,A*35
+$GPGGA,071410,5230.73,N,1319.35,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071410,A,5230.73,N,1319.35,E,7.7,89.0,030308,11.2,W,A*3d
+$GPGGA,071411,5230.73,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071411,A,5230.73,N,1319.36,E,7.2,31.0,030308,11.2,W,A*39
+$GPGGA,071412,5230.73,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071412,A,5230.73,N,1319.36,E,6.7,31.0,030308,11.2,W,A*3e
+$GPGGA,071413,5230.73,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071413,A,5230.73,N,1319.36,E,6.7,31.0,030308,11.2,W,A*3f
+$GPGGA,071414,5230.73,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071414,A,5230.73,N,1319.36,E,5.8,89.0,030308,11.2,W,A*37
+$GPGGA,071415,5230.73,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071415,A,5230.73,N,1319.36,E,7.7,89.0,030308,11.2,W,A*3b
+$GPGGA,071416,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071416,A,5230.74,N,1319.37,E,8.4,31.0,030308,11.2,W,A*31
+$GPGGA,071417,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071417,A,5230.74,N,1319.37,E,7.7,31.0,030308,11.2,W,A*3c
+$GPGGA,071418,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071418,A,5230.74,N,1319.37,E,7.7,31.0,030308,11.2,W,A*33
+$GPGGA,071419,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071419,A,5230.74,N,1319.37,E,4.9,31.0,030308,11.2,W,A*3f
+$GPGGA,071420,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071420,A,5230.74,N,1319.37,E,6.7,31.0,030308,11.2,W,A*39
+$GPGGA,071421,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071421,A,5230.74,N,1319.37,E,nan,31.0,030308,11.2,W,A*76
+$GPGGA,071422,5230.74,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071422,A,5230.74,N,1319.37,E,9.2,89.0,030308,11.2,W,A*32
+$GPGGA,071423,5230.75,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071423,A,5230.75,N,1319.37,E,7.1,89.0,030308,11.2,W,A*3f
+$GPGGA,071424,5230.75,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071424,A,5230.75,N,1319.37,E,5.1,89.0,030308,11.2,W,A*3a
+$GPGGA,071425,5230.75,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071425,A,5230.75,N,1319.37,E,5.9,89.0,030308,11.2,W,A*33
+$GPGGA,071426,5230.75,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071426,A,5230.75,N,1319.37,E,5.1,89.0,030308,11.2,W,A*38
+$GPGGA,071427,5230.75,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071427,A,5230.75,N,1319.37,E,1.7,89.0,030308,11.2,W,A*3b
+$GPGGA,071428,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071428,A,5230.76,N,1319.37,E,2.8,89.0,030308,11.2,W,A*3b
+$GPGGA,071429,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071429,A,5230.76,N,1319.37,E,4.1,89.0,030308,11.2,W,A*35
+$GPGGA,071430,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071430,A,5230.76,N,1319.37,E,2.5,89.0,030308,11.2,W,A*3f
+$GPGGA,071431,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071431,A,5230.76,N,1319.37,E,1.7,89.0,030308,11.2,W,A*3f
+$GPGGA,071432,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071432,A,5230.76,N,1319.37,E,5.0,89.0,030308,11.2,W,A*3f
+$GPGGA,071433,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071433,A,5230.76,N,1319.37,E,4.1,89.0,030308,11.2,W,A*3e
+$GPGGA,071434,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071434,A,5230.76,N,1319.37,E,4.1,89.0,030308,11.2,W,A*39
+$GPGGA,071435,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071435,A,5230.76,N,1319.37,E,2.5,89.0,030308,11.2,W,A*3a
+$GPGGA,071436,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071436,A,5230.76,N,1319.37,E,4.1,89.0,030308,11.2,W,A*3b
+$GPGGA,071437,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071437,A,5230.76,N,1319.37,E,2.5,89.0,030308,11.2,W,A*38
+$GPGGA,071438,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071438,A,5230.76,N,1319.37,E,1.7,89.0,030308,11.2,W,A*36
+$GPGGA,071439,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071439,A,5230.76,N,1319.37,E,2.8,89.0,030308,11.2,W,A*3b
+$GPGGA,071440,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071440,A,5230.76,N,1319.37,E,1.7,89.0,030308,11.2,W,A*39
+$GPGGA,071441,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071441,A,5230.76,N,1319.37,E,5.1,89.0,030308,11.2,W,A*3a
+$GPGGA,071442,5230.76,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071442,A,5230.76,N,1319.37,E,1.7,89.0,030308,11.2,W,A*3b
+$GPGGA,071443,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071443,A,5230.77,N,1319.37,E,2.8,89.0,030308,11.2,W,A*37
+$GPGGA,071444,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071444,A,5230.77,N,1319.37,E,2.5,89.0,030308,11.2,W,A*3d
+$GPGGA,071445,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071445,A,5230.77,N,1319.37,E,1.7,89.0,030308,11.2,W,A*3d
+$GPGGA,071446,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071446,A,5230.77,N,1319.37,E,2.8,89.0,030308,11.2,W,A*32
+$GPGGA,071447,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071447,A,5230.77,N,1319.37,E,1.7,89.0,030308,11.2,W,A*3f
+$GPGGA,071448,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071448,A,5230.77,N,1319.37,E,2.8,89.0,030308,11.2,W,A*3c
+$GPGGA,071449,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071449,A,5230.77,N,1319.37,E,1.3,89.0,030308,11.2,W,A*35
+$GPGGA,071450,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071450,A,5230.77,N,1319.37,E,2.5,89.0,030308,11.2,W,A*38
+$GPGGA,071451,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071451,A,5230.77,N,1319.37,E,9.8,329.0,030308,11.2,W,A*06
+$GPGGA,071452,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071452,A,5230.77,N,1319.37,E,2.5,329.0,030308,11.2,W,A*03
+$GPGGA,071453,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071453,A,5230.77,N,1319.37,E,3.1,329.0,030308,11.2,W,A*07
+$GPGGA,071454,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071454,A,5230.77,N,1319.37,E,5.1,329.0,030308,11.2,W,A*06
+$GPGGA,071455,5230.77,N,1319.37,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071455,A,5230.77,N,1319.37,E,8.5,329.0,030308,11.2,W,A*0e
+$GPGGA,071456,5230.78,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071456,A,5230.78,N,1319.36,E,9.8,328.0,030308,11.2,W,A*0e
+$GPGGA,071457,5230.78,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071457,A,5230.78,N,1319.36,E,8.4,328.0,030308,11.2,W,A*02
+$GPGGA,071458,5230.78,N,1319.36,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071458,A,5230.78,N,1319.36,E,12.4,270.0,030308,11.2,W,A*3a
+$GPGGA,071459,5230.79,N,1319.35,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071459,A,5230.79,N,1319.35,E,17.0,328.0,030308,11.2,W,A*34
+$GPGGA,071500,5230.79,N,1319.34,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071500,A,5230.79,N,1319.34,E,12.4,270.0,030308,11.2,W,A*35
+$GPGGA,071501,5230.79,N,1319.34,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071501,A,5230.79,N,1319.34,E,18.1,328.0,030308,11.2,W,A*37
+$GPGGA,071502,5230.79,N,1319.33,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071502,A,5230.79,N,1319.33,E,9.4,270.0,030308,11.2,W,A*0a
+$GPGGA,071503,5230.79,N,1319.33,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071503,A,5230.79,N,1319.33,E,10.8,270.0,030308,11.2,W,A*3f
+$GPGGA,071504,5230.79,N,1319.33,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071504,A,5230.79,N,1319.33,E,12.1,270.0,030308,11.2,W,A*33
+$GPGGA,071505,5230.79,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071505,A,5230.79,N,1319.31,E,18.5,270.0,030308,11.2,W,A*3e
+$GPGGA,071506,5230.79,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071506,A,5230.79,N,1319.31,E,2.6,270.0,030308,11.2,W,A*05
+$GPGGA,071507,5230.79,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071507,A,5230.79,N,1319.31,E,2.6,270.0,030308,11.2,W,A*04
+$GPGGA,071508,5230.79,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071508,A,5230.79,N,1319.31,E,3.9,270.0,030308,11.2,W,A*05
+$GPGGA,071509,5230.79,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071509,A,5230.79,N,1319.31,E,4.0,270.0,030308,11.2,W,A*0a
+$GPGGA,071510,5230.79,N,1319.31,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071510,A,5230.79,N,1319.31,E,5.3,270.0,030308,11.2,W,A*00
+$GPGGA,071511,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,071511,A,5230.79,N,1319.3,E,5.3,270.0,030308,11.2,W,A*30
+$GPGGA,071512,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,071512,A,5230.79,N,1319.3,E,5.3,270.0,030308,11.2,W,A*33
+$GPGGA,071513,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*7e
+$GPRMC,071513,A,5230.79,N,1319.3,E,3.9,270.0,030308,11.2,W,A*3e
+$GPGGA,071514,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,071514,A,5230.79,N,1319.3,E,4.0,270.0,030308,11.2,W,A*37
+$GPGGA,071515,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,071515,A,5230.79,N,1319.3,E,3.1,270.0,030308,11.2,W,A*30
+$GPGGA,071516,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*7b
+$GPRMC,071516,A,5230.79,N,1319.3,E,2.5,270.0,030308,11.2,W,A*36
+$GPGGA,071517,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,071517,A,5230.79,N,1319.3,E,4.0,270.0,030308,11.2,W,A*34
+$GPGGA,071518,5230.79,N,1319.3,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,071518,A,5230.79,N,1319.3,E,nan,270.0,030308,11.2,W,A*70
+$GPGGA,071519,5230.79,N,1319.29,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071519,A,5230.79,N,1319.29,E,6.5,270.0,030308,11.2,W,A*05
+$GPGGA,071520,5230.79,N,1319.29,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071520,A,5230.79,N,1319.29,E,6.9,270.0,030308,11.2,W,A*03
+$GPGGA,071521,5230.79,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071521,A,5230.79,N,1319.28,E,14.1,270.0,030308,11.2,W,A*38
+$GPGGA,071522,5230.79,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071522,A,5230.79,N,1319.28,E,10.1,270.0,030308,11.2,W,A*3f
+$GPGGA,071523,5230.79,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071523,A,5230.79,N,1319.28,E,2.6,270.0,030308,11.2,W,A*0a
+$GPGGA,071524,5230.79,N,1319.28,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071524,A,5230.79,N,1319.28,E,3.1,270.0,030308,11.2,W,A*0b
+$GPGGA,071525,5230.79,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071525,A,5230.79,N,1319.27,E,2.6,270.0,030308,11.2,W,A*03
+$GPGGA,071526,5230.8,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*78
+$GPRMC,071526,A,5230.8,N,1319.27,E,3.6,270.0,030308,11.2,W,A*37
+$GPGGA,071527,5230.8,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*79
+$GPRMC,071527,A,5230.8,N,1319.27,E,2.6,270.0,030308,11.2,W,A*37
+$GPGGA,071528,5230.8,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*76
+$GPRMC,071528,A,5230.8,N,1319.27,E,2.8,270.0,030308,11.2,W,A*36
+$GPGGA,071529,5230.8,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,071529,A,5230.8,N,1319.27,E,3.1,270.0,030308,11.2,W,A*3f
+$GPGGA,071530,5230.8,N,1319.27,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,071530,A,5230.8,N,1319.27,E,14.7,270.0,030308,11.2,W,A*07
+$GPGGA,071531,5230.8,N,1319.25,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,071531,A,5230.8,N,1319.25,E,38.4,298.0,030308,11.2,W,A*0f
+$GPGGA,071532,5230.81,N,1319.23,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071532,A,5230.81,N,1319.23,E,49.7,298.0,030308,11.2,W,A*3e
+$GPGGA,071533,5230.82,N,1319.22,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071533,A,5230.82,N,1319.22,E,30.6,309.0,030308,11.2,W,A*3b
+$GPGGA,071534,5230.82,N,1319.21,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071534,A,5230.82,N,1319.21,E,12.5,270.0,030308,11.2,W,A*33
+$GPGGA,071535,5230.82,N,1319.2,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,071535,A,5230.82,N,1319.2,E,22.1,270.0,030308,11.2,W,A*04
+$GPGGA,071536,5230.82,N,1319.19,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071536,A,5230.82,N,1319.19,E,21.5,270.0,030308,11.2,W,A*3a
+$GPGGA,071537,5230.82,N,1319.18,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071537,A,5230.82,N,1319.18,E,24.5,309.0,030308,11.2,W,A*30
+$GPGGA,071538,5230.82,N,1319.18,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071538,A,5230.82,N,1319.18,E,18.9,270.0,030308,11.2,W,A*33
+$GPGGA,071539,5230.82,N,1319.16,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071539,A,5230.82,N,1319.16,E,31.6,270.0,030308,11.2,W,A*38
+$GPGGA,071540,5230.83,N,1319.14,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071540,A,5230.83,N,1319.14,E,41.6,299.0,030308,11.2,W,A*35
+$GPGGA,071541,5230.83,N,1319.13,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071541,A,5230.83,N,1319.13,E,33.6,270.0,030308,11.2,W,A*31
+$GPGGA,071542,5230.83,N,1319.12,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071542,A,5230.83,N,1319.12,E,24.6,270.0,030308,11.2,W,A*35
+$GPGGA,071543,5230.83,N,1319.1,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,071543,A,5230.83,N,1319.1,E,23.3,309.0,030308,11.2,W,A*0b
+$GPGGA,071544,5230.83,N,1319.1,E,1,07,1.3,50.6,M,39.2,M,,*7b
+$GPRMC,071544,A,5230.83,N,1319.1,E,21.5,270.0,030308,11.2,W,A*07
+$GPGGA,071545,5230.83,N,1319.09,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071545,A,5230.83,N,1319.09,E,1.4,270.0,030308,11.2,W,A*0d
+$GPGGA,071546,5230.83,N,1319.09,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071546,A,5230.83,N,1319.09,E,24.5,270.0,030308,11.2,W,A*38
+$GPGGA,071547,5230.84,N,1319.07,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071547,A,5230.84,N,1319.07,E,20.9,309.0,030308,11.2,W,A*37
+$GPGGA,071548,5230.84,N,1319.07,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071548,A,5230.84,N,1319.07,E,17.6,270.0,030308,11.2,W,A*3c
+$GPGGA,071549,5230.84,N,1319.06,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071549,A,5230.84,N,1319.06,E,19.6,270.0,030308,11.2,W,A*32
+$GPGGA,071550,5230.84,N,1319.04,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071550,A,5230.84,N,1319.04,E,32.1,270.0,030308,11.2,W,A*36
+$GPGGA,071551,5230.85,N,1319.04,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071551,A,5230.85,N,1319.04,E,17.1,328.0,030308,11.2,W,A*3d
+$GPGGA,071552,5230.85,N,1319.03,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071552,A,5230.85,N,1319.03,E,20.2,270.0,030308,11.2,W,A*32
+$GPGGA,071553,5230.85,N,1319.02,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071553,A,5230.85,N,1319.02,E,15.9,270.0,030308,11.2,W,A*3f
+$GPGGA,071554,5230.85,N,1319.01,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071554,A,5230.85,N,1319.01,E,26.0,328.0,030308,11.2,W,A*3e
+$GPGGA,071555,5230.86,N,1319,E,1,07,1.3,50.6,M,39.2,M,,*61
+$GPRMC,071555,A,5230.86,N,1319,E,22.6,310.0,030308,11.2,W,A*1a
+$GPGGA,071556,5230.86,N,1319,E,1,07,1.3,50.6,M,39.2,M,,*62
+$GPRMC,071556,A,5230.86,N,1319,E,21.7,270.0,030308,11.2,W,A*1c
+$GPGGA,071557,5230.86,N,1318.98,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071557,A,5230.86,N,1318.98,E,24.5,309.0,030308,11.2,W,A*3b
+$GPGGA,071558,5230.86,N,1318.98,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071558,A,5230.86,N,1318.98,E,23.6,270.0,030308,11.2,W,A*3f
+$GPGGA,071559,5230.87,N,1318.95,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071559,A,5230.87,N,1318.95,E,57.8,292.0,030308,11.2,W,A*33
+$GPGGA,071600,5230.88,N,1318.93,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071600,A,5230.88,N,1318.93,E,60.9,309.0,030308,11.2,W,A*33
+$GPGGA,071601,5230.88,N,1318.91,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071601,A,5230.88,N,1318.91,E,34.9,270.0,030308,11.2,W,A*3e
+$GPGGA,071602,5230.89,N,1318.88,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071602,A,5230.89,N,1318.88,E,75.6,303.0,030308,11.2,W,A*3b
+$GPGGA,071603,5230.91,N,1318.85,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071603,A,5230.91,N,1318.85,E,82.2,303.0,030308,11.2,W,A*32
+$GPGGA,071604,5230.91,N,1318.82,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071604,A,5230.91,N,1318.82,E,63.2,288.0,030308,11.2,W,A*3f
+$GPGGA,071605,5230.92,N,1318.81,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071605,A,5230.92,N,1318.81,E,29.4,309.0,030308,11.2,W,A*3e
+$GPGGA,071606,5230.97,N,1318.63,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071606,A,5230.97,N,1318.63,E,388.8,296.0,030308,11.2,W,A*07
+$GPGGA,071607,5231.02,N,1318.49,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071607,A,5231.02,N,1318.49,E,356.1,298.0,030308,11.2,W,A*07
+$GPGGA,071608,5231.03,N,1318.48,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071608,A,5231.03,N,1318.48,E,23.0,329.0,030308,11.2,W,A*33
+$GPGGA,071609,5231.03,N,1318.47,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071609,A,5231.03,N,1318.47,E,8.8,270.0,030308,11.2,W,A*01
+$GPGGA,071610,5231.03,N,1318.46,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071610,A,5231.03,N,1318.46,E,33.8,270.0,030308,11.2,W,A*30
+$GPGGA,071611,5231.03,N,1318.46,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071611,A,5231.03,N,1318.46,E,15.9,328.0,030308,11.2,W,A*38
+$GPGGA,071612,5231.03,N,1318.45,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071612,A,5231.03,N,1318.45,E,11.3,270.0,030308,11.2,W,A*3a
+$GPGGA,071613,5231.03,N,1318.44,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071613,A,5231.03,N,1318.44,E,11.4,270.0,030308,11.2,W,A*3d
+$GPGGA,071614,5231.04,N,1318.44,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071614,A,5231.04,N,1318.44,E,13.5,328.0,030308,11.2,W,A*32
+$GPGGA,071615,5231.04,N,1318.44,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071615,A,5231.04,N,1318.44,E,10.9,328.0,030308,11.2,W,A*3c
+$GPGGA,071616,5231.04,N,1318.43,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071616,A,5231.04,N,1318.43,E,13.5,270.0,030308,11.2,W,A*3b
+$GPGGA,071617,5231.04,N,1318.42,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071617,A,5231.04,N,1318.42,E,21.4,309.0,030308,11.2,W,A*34
+$GPGGA,071618,5231.04,N,1318.41,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071618,A,5231.04,N,1318.41,E,34.1,270.0,030308,11.2,W,A*36
+$GPGGA,071619,5231.05,N,1318.4,E,1,07,1.3,50.6,M,39.2,M,,*7b
+$GPRMC,071619,A,5231.05,N,1318.4,E,20.2,329.0,030308,11.2,W,A*0c
+$GPGGA,071620,5231.06,N,1318.38,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071620,A,5231.06,N,1318.38,E,34.9,298.0,030308,11.2,W,A*3f
+$GPGGA,071621,5231.06,N,1318.37,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071621,A,5231.06,N,1318.37,E,54.3,298.0,030308,11.2,W,A*3d
+$GPGGA,071622,5231.07,N,1318.34,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071622,A,5231.07,N,1318.34,E,51.9,292.0,030308,11.2,W,A*39
+$GPGGA,071623,5231.07,N,1318.34,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071623,A,5231.07,N,1318.34,E,8.9,270.0,030308,11.2,W,A*08
+$GPGGA,071624,5231.07,N,1318.34,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071624,A,5231.07,N,1318.34,E,10.1,270.0,030308,11.2,W,A*3e
+$GPGGA,071625,5231.07,N,1318.33,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071625,A,5231.07,N,1318.33,E,14.1,270.0,030308,11.2,W,A*3c
+$GPGGA,071626,5231.07,N,1318.32,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071626,A,5231.07,N,1318.32,E,14.7,328.0,030308,11.2,W,A*34
+$GPGGA,071627,5231.07,N,1318.32,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071627,A,5231.07,N,1318.32,E,15.6,270.0,030308,11.2,W,A*39
+$GPGGA,071628,5231.08,N,1318.29,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071628,A,5231.08,N,1318.29,E,53.1,292.0,030308,11.2,W,A*3a
+$GPGGA,071629,5231.09,N,1318.26,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071629,A,5231.09,N,1318.26,E,72.1,303.0,030308,11.2,W,A*3f
+$GPGGA,071630,5231.13,N,1318.14,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071630,A,5231.13,N,1318.14,E,311.2,295.0,030308,11.2,W,A*06
+$GPGGA,071631,5231.15,N,1318.08,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071631,A,5231.15,N,1318.08,E,148.7,303.0,030308,11.2,W,A*09
+$GPGGA,071632,5231.16,N,1318.05,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071632,A,5231.16,N,1318.05,E,73.3,288.0,030308,11.2,W,A*3b
+$GPGGA,071633,5231.17,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071633,A,5231.17,N,1318.01,E,101.1,298.0,030308,11.2,W,A*08
+$GPGGA,071634,5231.18,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*62
+$GPRMC,071634,A,5231.18,N,1318,E,26.0,309.0,030308,11.2,W,A*13
+$GPGGA,071635,5231.18,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071635,A,5231.18,N,1317.99,E,18.3,270.0,030308,11.2,W,A*32
+$GPGGA,071636,5231.18,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071636,A,5231.18,N,1317.99,E,11.7,270.0,030308,11.2,W,A*3c
+$GPGGA,071637,5231.18,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071637,A,5231.18,N,1317.98,E,16.4,328.0,030308,11.2,W,A*34
+$GPGGA,071638,5231.18,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071638,A,5231.18,N,1317.98,E,nan,328.0,030308,11.2,W,A*47
+$GPGGA,071639,5231.19,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071639,A,5231.19,N,1317.98,E,32.4,328.0,030308,11.2,W,A*3d
+$GPGGA,071640,5231.2,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*7a
+$GPRMC,071640,A,5231.2,N,1317.98,E,48.2,328.0,030308,11.2,W,A*02
+$GPGGA,071641,5231.21,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071641,A,5231.21,N,1317.98,E,34.8,328.0,030308,11.2,W,A*33
+$GPGGA,071642,5231.22,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071642,A,5231.22,N,1317.98,E,32.3,328.0,030308,11.2,W,A*3e
+$GPGGA,071643,5231.22,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071643,A,5231.22,N,1317.97,E,14.9,328.0,030308,11.2,W,A*3e
+$GPGGA,071644,5231.23,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071644,A,5231.23,N,1317.97,E,15.7,328.0,030308,11.2,W,A*37
+$GPGGA,071645,5231.24,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071645,A,5231.24,N,1317.97,E,17.4,328.0,030308,11.2,W,A*30
+$GPGGA,071646,5231.24,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071646,A,5231.24,N,1317.97,E,12.4,328.0,030308,11.2,W,A*36
+$GPGGA,071647,5231.24,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071647,A,5231.24,N,1317.97,E,13.3,328.0,030308,11.2,W,A*31
+$GPGGA,071648,5231.24,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071648,A,5231.24,N,1317.97,E,10.8,328.0,030308,11.2,W,A*36
+$GPGGA,071649,5231.25,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071649,A,5231.25,N,1317.97,E,10.8,328.0,030308,11.2,W,A*36
+$GPGGA,071650,5231.25,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071650,A,5231.25,N,1317.98,E,18.1,31.0,030308,11.2,W,A*0b
+$GPGGA,071651,5231.25,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071651,A,5231.25,N,1317.98,E,18.1,31.0,030308,11.2,W,A*0a
+$GPGGA,071652,5231.27,N,1317.98,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071652,A,5231.27,N,1317.98,E,37.1,17.0,030308,11.2,W,A*02
+$GPGGA,071653,5231.27,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071653,A,5231.27,N,1317.99,E,30.0,31.0,030308,11.2,W,A*00
+$GPGGA,071654,5231.28,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071654,A,5231.28,N,1317.99,E,28.0,16.0,030308,11.2,W,A*04
+$GPGGA,071655,5231.28,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071655,A,5231.28,N,1317.99,E,0,16.0,030308,11.2,W,A*21
+$GPGGA,071656,5231.28,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071656,A,5231.28,N,1317.99,E,4.4,16.0,030308,11.2,W,A*3c
+$GPGGA,071657,5231.28,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071657,A,5231.28,N,1317.99,E,4.3,16.0,030308,11.2,W,A*3a
+$GPGGA,071658,5231.3,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*52
+$GPRMC,071658,A,5231.3,N,1318,E,53.2,17.0,030308,11.2,W,A*1f
+$GPGGA,071659,5231.3,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*53
+$GPRMC,071659,A,5231.3,N,1318,E,8.4,17.0,030308,11.2,W,A*26
+$GPGGA,071700,5231.3,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*5e
+$GPRMC,071700,A,5231.3,N,1318,E,6.7,17.0,030308,11.2,W,A*26
+$GPGGA,071701,5231.31,N,1318,E,1,07,1.3,50.6,M,39.2,M,,*6e
+$GPRMC,071701,A,5231.31,N,1318,E,14.9,17.0,030308,11.2,W,A*2b
+$GPGGA,071702,5231.33,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071702,A,5231.33,N,1318.02,E,77.5,31.0,030308,11.2,W,A*0b
+$GPGGA,071703,5231.33,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071703,A,5231.33,N,1318.02,E,1.7,31.0,030308,11.2,W,A*39
+$GPGGA,071704,5231.33,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071704,A,5231.33,N,1318.02,E,28.0,31.0,030308,11.2,W,A*02
+$GPGGA,071705,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071705,A,5231.35,N,1318.02,E,53.6,11.0,030308,11.2,W,A*0d
+$GPGGA,071706,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071706,A,5231.35,N,1318.02,E,6.6,11.0,030308,11.2,W,A*3e
+$GPGGA,071707,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071707,A,5231.35,N,1318.02,E,4.3,11.0,030308,11.2,W,A*38
+$GPGGA,071708,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071708,A,5231.35,N,1318.02,E,6.6,11.0,030308,11.2,W,A*30
+$GPGGA,071709,5231.35,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071709,A,5231.35,N,1318.02,E,0,11.0,030308,11.2,W,A*2f
+$GPGGA,071710,5231.36,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071710,A,5231.36,N,1318.02,E,9.8,11.0,030308,11.2,W,A*3b
+$GPGGA,071711,5231.36,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071711,A,5231.36,N,1318.02,E,5.8,11.0,030308,11.2,W,A*36
+$GPGGA,071712,5231.36,N,1318.02,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071712,A,5231.36,N,1318.02,E,10.5,270.0,030308,11.2,W,A*39
+$GPGGA,071713,5231.37,N,1318.01,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071713,A,5231.37,N,1318.01,E,45.1,329.0,030308,11.2,W,A*33
+$GPGGA,071714,5231.37,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071714,A,5231.37,N,1317.99,E,33.2,309.0,030308,11.2,W,A*3a
+$GPGGA,071715,5231.38,N,1317.99,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071715,A,5231.38,N,1317.99,E,11.3,309.0,030308,11.2,W,A*35
+$GPGGA,071716,5231.4,N,1317.97,E,1,07,1.3,50.6,M,39.2,M,,*71
+$GPRMC,071716,A,5231.4,N,1317.97,E,91.1,321.0,030308,11.2,W,A*07
+$GPGGA,071717,5231.42,N,1317.95,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071717,A,5231.42,N,1317.95,E,89.6,321.0,030308,11.2,W,A*38
+$GPGGA,071718,5231.45,N,1317.9,E,1,07,1.3,50.6,M,39.2,M,,*7d
+$GPRMC,071718,A,5231.45,N,1317.9,E,155.6,324.0,030308,11.2,W,A*30
+$GPGGA,071719,5231.46,N,1317.9,E,1,07,1.3,50.6,M,39.2,M,,*7f
+$GPRMC,071719,A,5231.46,N,1317.9,E,19.4,328.0,030308,11.2,W,A*05
+$GPGGA,071720,5231.46,N,1317.9,E,1,07,1.3,50.6,M,39.2,M,,*75
+$GPRMC,071720,A,5231.46,N,1317.9,E,25.6,328.0,030308,11.2,W,A*02
+$GPGGA,071721,5231.48,N,1317.89,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071721,A,5231.48,N,1317.89,E,43.0,329.0,030308,11.2,W,A*32
+$GPGGA,071722,5231.49,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071722,A,5231.49,N,1317.87,E,65.0,337.0,030308,11.2,W,A*35
+$GPGGA,071723,5231.5,N,1317.87,E,1,07,1.3,50.6,M,39.2,M,,*77
+$GPRMC,071723,A,5231.5,N,1317.87,E,37.8,337.0,030308,11.2,W,A*03
+$GPGGA,071724,5231.52,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071724,A,5231.52,N,1317.86,E,91.0,342.0,030308,11.2,W,A*31
+$GPGGA,071725,5231.53,N,1317.86,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071725,A,5231.53,N,1317.86,E,21.6,342.0,030308,11.2,W,A*3c
+$GPGGA,071726,5231.59,N,1317.84,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071726,A,5231.59,N,1317.84,E,214.9,349.0,030308,11.2,W,A*07
+$GPGGA,071727,5231.67,N,1317.82,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071727,A,5231.67,N,1317.82,E,280.1,349.0,030308,11.2,W,A*08
+$GPGGA,071728,5231.71,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071728,A,5231.71,N,1317.81,E,156.5,350.0,030308,11.2,W,A*07
+$GPGGA,071729,5231.72,N,1317.81,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071729,A,5231.72,N,1317.81,E,20.2,350.0,030308,11.2,W,A*32
+$GPGGA,071730,5231.73,N,1317.8,E,1,07,1.3,50.6,M,39.2,M,,*73
+$GPRMC,071730,A,5231.73,N,1317.8,E,59.3,348.0,030308,11.2,W,A*0c
+$GPGGA,071731,5231.75,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071731,A,5231.75,N,1317.79,E,51.3,328.0,030308,11.2,W,A*33
+$GPGGA,071732,5231.75,N,1317.79,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071732,A,5231.75,N,1317.79,E,27.2,328.0,030308,11.2,W,A*30
+$GPGGA,071733,5231.76,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071733,A,5231.76,N,1317.78,E,30.8,328.0,030308,11.2,W,A*3f
+$GPGGA,071734,5231.78,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071734,A,5231.78,N,1317.78,E,57.7,348.0,030308,11.2,W,A*3e
+$GPGGA,071735,5231.78,N,1317.78,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071735,A,5231.78,N,1317.78,E,7.1,348.0,030308,11.2,W,A*0c
+$GPGGA,071736,5231.82,N,1317.76,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071736,A,5231.82,N,1317.76,E,180.5,347.0,030308,11.2,W,A*01
+$GPGGA,071737,5231.84,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071737,A,5231.84,N,1317.75,E,41.5,343.0,030308,11.2,W,A*3d
+$GPGGA,071738,5231.85,N,1317.75,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071738,A,5231.85,N,1317.75,E,64.7,348.0,030308,11.2,W,A*3d
+$GPGGA,071739,5231.87,N,1317.74,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071739,A,5231.87,N,1317.74,E,63.8,348.0,030308,11.2,W,A*37
+$GPGGA,071740,5231.9,N,1317.72,E,1,07,1.3,50.6,M,39.2,M,,*74
+$GPRMC,071740,A,5231.9,N,1317.72,E,109.9,339.0,030308,11.2,W,A*33
+$GPGGA,071741,5231.92,N,1317.71,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071741,A,5231.92,N,1317.71,E,63.2,338.0,030308,11.2,W,A*34
+$GPGGA,071742,5231.94,N,1317.7,E,1,07,1.3,50.6,M,39.2,M,,*70
+$GPRMC,071742,A,5231.94,N,1317.7,E,77.7,337.0,030308,11.2,W,A*0f
+$GPGGA,071743,5231.94,N,1317.69,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071743,A,5231.94,N,1317.69,E,25.2,328.0,030308,11.2,W,A*3a
+$GPGGA,071744,5231.94,N,1317.69,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071744,A,5231.94,N,1317.69,E,4.9,328.0,030308,11.2,W,A*05
+$GPGGA,071745,5231.97,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071745,A,5231.97,N,1317.68,E,85.2,343.0,030308,11.2,W,A*39
+$GPGGA,071746,5231.97,N,1317.68,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071746,A,5231.97,N,1317.68,E,22.5,329.0,030308,11.2,W,A*3c
+$GPGGA,071747,5231.99,N,1317.67,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071747,A,5231.99,N,1317.67,E,55.6,343.0,030308,11.2,W,A*33
+$GPGGA,071748,5232,N,1317.66,E,1,07,1.3,50.6,M,39.2,M,,*6d
+$GPRMC,071748,A,5232,N,1317.66,E,41.4,342.0,030308,11.2,W,A*16
+$GPGGA,071749,5232.01,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071749,A,5232.01,N,1317.65,E,44.2,328.0,030308,11.2,W,A*34
+$GPGGA,071750,5232.02,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071750,A,5232.02,N,1317.65,E,13.8,328.0,030308,11.2,W,A*37
+$GPGGA,071751,5232.02,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4a
+$GPRMC,071751,A,5232.02,N,1317.65,E,20.9,328.0,030308,11.2,W,A*37
+$GPGGA,071752,5232.02,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*49
+$GPRMC,071752,A,5232.02,N,1317.65,E,12.0,328.0,030308,11.2,W,A*3c
+$GPGGA,071753,5232.02,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*48
+$GPRMC,071753,A,5232.02,N,1317.65,E,11.0,328.0,030308,11.2,W,A*3e
+$GPGGA,071754,5232.03,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071754,A,5232.03,N,1317.65,E,13.5,328.0,030308,11.2,W,A*3f
+$GPGGA,071755,5232.03,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071755,A,5232.03,N,1317.64,E,20.5,329.0,030308,11.2,W,A*3e
+$GPGGA,071756,5232.03,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071756,A,5232.03,N,1317.64,E,9.2,329.0,030308,11.2,W,A*01
+$GPGGA,071757,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4b
+$GPRMC,071757,A,5232.04,N,1317.64,E,11.0,329.0,030308,11.2,W,A*3c
+$GPGGA,071758,5232.04,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071758,A,5232.04,N,1317.64,E,6.6,329.0,030308,11.2,W,A*03
+$GPGGA,071759,5232.05,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071759,A,5232.05,N,1317.64,E,29.8,329.0,030308,11.2,W,A*30
+$GPGGA,071800,5232.05,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071800,A,5232.05,N,1317.64,E,0.3,329.0,030308,11.2,W,A*03
+$GPGGA,071801,5232.05,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071801,A,5232.05,N,1317.64,E,3.6,329.0,030308,11.2,W,A*04
+$GPGGA,071802,5232.05,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071802,A,5232.05,N,1317.65,E,4.2,89.0,030308,11.2,W,A*3c
+$GPGGA,071803,5232.05,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071803,A,5232.05,N,1317.65,E,5.6,89.0,030308,11.2,W,A*38
+$GPGGA,071804,5232.05,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*42
+$GPRMC,071804,A,5232.05,N,1317.65,E,3.1,89.0,030308,11.2,W,A*3e
+$GPGGA,071805,5232.05,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*43
+$GPRMC,071805,A,5232.05,N,1317.65,E,5.6,89.0,030308,11.2,W,A*3e
+$GPGGA,071806,5232.05,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*40
+$GPRMC,071806,A,5232.05,N,1317.65,E,3.1,89.0,030308,11.2,W,A*3c
+$GPGGA,071807,5232.05,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*41
+$GPRMC,071807,A,5232.05,N,1317.65,E,4.9,89.0,030308,11.2,W,A*32
+$GPGGA,071808,5232.06,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071808,A,5232.06,N,1317.65,E,5.1,89.0,030308,11.2,W,A*37
+$GPGGA,071809,5232.06,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071809,A,5232.06,N,1317.65,E,18.5,89.0,030308,11.2,W,A*0e
+$GPGGA,071810,5232.06,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071810,A,5232.06,N,1317.65,E,10.8,89.0,030308,11.2,W,A*03
+$GPGGA,071811,5232.06,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*45
+$GPRMC,071811,A,5232.06,N,1317.65,E,8.2,89.0,030308,11.2,W,A*31
+$GPGGA,071812,5232.07,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*47
+$GPRMC,071812,A,5232.07,N,1317.65,E,11.0,89.0,030308,11.2,W,A*09
+$GPGGA,071813,5232.07,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*46
+$GPRMC,071813,A,5232.07,N,1317.65,E,11.0,89.0,030308,11.2,W,A*08
+$GPGGA,071814,5232.08,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4e
+$GPRMC,071814,A,5232.08,N,1317.65,E,9.9,89.0,030308,11.2,W,A*30
+$GPGGA,071815,5232.08,N,1317.65,E,1,07,1.3,50.6,M,39.2,M,,*4f
+$GPRMC,071815,A,5232.08,N,1317.65,E,22.6,328.0,030308,11.2,W,A*3f
+$GPGGA,071816,5232.08,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4d
+$GPRMC,071816,A,5232.08,N,1317.64,E,6.7,270.0,030308,11.2,W,A*06
+$GPGGA,071817,5232.08,N,1317.64,E,1,07,1.3,50.6,M,39.2,M,,*4c
+$GPRMC,071817,A,5232.08,N,1317.64,E,7.8,270.0,030308,11.2,W,A*09
+$GPGGA,071818,5232.08,N,1317.63,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071818,A,5232.08,N,1317.63,E,20.8,270.0,030308,11.2,W,A*34
+$GPGGA,071819,5232.08,N,1317.62,E,1,07,1.3,50.6,M,39.2,M,,*44
+$GPRMC,071819,A,5232.08,N,1317.62,E,29.0,270.0,030308,11.2,W,A*35
+$GPGGA,071820,5232.08,N,1317.6,E,1,07,1.3,50.6,M,39.2,M,,*7c
+$GPRMC,071820,A,5232.08,N,1317.6,E,28.3,270.0,030308,11.2,W,A*0f
diff --git a/CenterConsole/sysui/CenterScreen.qml b/CenterConsole/sysui/CenterScreen.qml
new file mode 100644
index 0000000..cd6f45d
--- /dev/null
+++ b/CenterConsole/sysui/CenterScreen.qml
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.0
+import QtLocation 5.5
+import QtPositioning 5.5
+
+import controls 1.0
+import utils 1.0
+import service.valuesource 1.0
+
+import "Launcher"
+import "CenterItems"
+
+Item {
+ id: root
+ property int visibleScreenHeight: Style.screenHeight - Style.bottomBarHeight
+ - Style.statusBarHeight
+ width: Style.screenWidth
+ height: visibleScreenHeight
+ state: "enterCar"
+
+ property int searchInvisibleHeight: visibleScreenHeight + Style.searchInputHeight
+ + Style.bottomBarHeight + searchInput.panelHeight + 30
+ property int searchVisibleHeight: visibleScreenHeight + searchInput.panelHeight
+ property int invisibleY: visibleScreenHeight + Style.bottomBarHeight
+
+
+ MapPage {
+ id: mapPage
+ property alias mapState: root.state
+ height: visibleScreenHeight
+ }
+
+ SearchInput {
+ id: searchInput
+ y: searchInvisibleHeight
+ property alias mapState: root.state
+ }
+
+ DestinationInfo {
+ id: destinationInfo
+ y: invisibleY
+ property alias mapState: root.state
+ }
+
+ LauncherBar {
+ id: launcherBar
+ y: visibleScreenHeight - launcherBar.height
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+ states: [
+ State {
+ name: "enterCar"
+ PropertyChanges {
+ target: mapPage
+ navigationStarted: false
+ }
+ },
+ State {
+ name: "selectDestination"
+ PropertyChanges {
+ target: launcherBar
+ y: invisibleY
+ }
+ PropertyChanges {
+ target: destinationInfo
+ y: invisibleY
+ }
+ PropertyChanges {
+ target: mapPage
+ navigationStarted: false
+ }
+ PropertyChanges {
+ target: searchInput
+ y: searchVisibleHeight
+ }
+ },
+ State {
+ name: "showRoute"
+ PropertyChanges {
+ target: launcherBar
+ y: invisibleY
+ }
+ PropertyChanges {
+ target: destinationInfo
+ y: visibleScreenHeight - destinationInfo.height
+ }
+ PropertyChanges {
+ target: mapPage
+ navigationStarted: false
+ }
+ StateChangeScript {
+ script: {
+ mapPage.showRoute()
+ }
+ }
+ },
+ State {
+ name: "driveStarted"
+ PropertyChanges {
+ target: launcherBar
+ y: invisibleY
+ }
+ PropertyChanges {
+ target: destinationInfo
+ y: invisibleY
+ }
+ PropertyChanges {
+ target: searchInput
+ y: searchVisibleHeight
+ } //Start route quidance
+ PropertyChanges {
+ target: mapPage
+ navigationStarted: true
+ }
+ },
+ State {
+ name: "navigationRunning"
+ PropertyChanges {
+ target: mapPage
+ navigationStarted: true
+ }
+ },
+ State {
+ name: "tripSummary"
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "enterCar"; to: "selectDestination"; reversible: true
+ SequentialAnimation {
+ NumberAnimation { target: launcherBar; properties: "y"; duration: 300 }
+ NumberAnimation { target: searchInput; properties: "y"; duration: 300 }
+ }
+ },
+ Transition {
+ from: "selectDestination"; to: "showRoute"; reversible: true
+ SequentialAnimation {
+ NumberAnimation { target: destinationInfo; properties: "y"; duration: 300 }
+ }
+ },
+ Transition {
+ from: "showRoute"; to: "driveStarted"; reversible: true
+ SequentialAnimation {
+ NumberAnimation { target: destinationInfo; properties: "y"; duration: 300 }
+ NumberAnimation { target: searchInput; properties: "y"; duration: 300 }
+ }
+
+ },
+ Transition {
+ from: "showRoute"; to: "enterCar"; reversible: true
+ SequentialAnimation {
+ NumberAnimation { target: destinationInfo; properties: "y"; duration: 300 }
+ NumberAnimation { target: launcherBar; properties: "y"; duration: 300 }
+ }
+ },
+ Transition {
+ from: "driveStarted"; to: "navigationRunning"; reversible: true
+ SequentialAnimation {
+ NumberAnimation { target: destinationInfo; properties: "y"; duration: 300 }
+ NumberAnimation { target: launcherBar; properties: "y"; duration: 300 }
+ }
+ }
+ ]
+ onStateChanged: console.log("State: "+state)
+}
+
diff --git a/CenterConsole/sysui/Keyboard.qml b/CenterConsole/sysui/Keyboard.qml
new file mode 100644
index 0000000..72186d1
--- /dev/null
+++ b/CenterConsole/sysui/Keyboard.qml
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import QtQuick.VirtualKeyboard 2.1
+import QtQuick.VirtualKeyboard.Settings 2.1
+
+InputPanel {
+ visible: active
+
+ Component.onCompleted: {
+ VirtualKeyboardSettings.styleName = "neptune"
+ }
+}
diff --git a/CenterConsole/sysui/LaunchController.qml b/CenterConsole/sysui/LaunchController.qml
new file mode 100644
index 0000000..af30dd8
--- /dev/null
+++ b/CenterConsole/sysui/LaunchController.qml
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 1.0
+import controls 1.0
+import utils 1.0
+import models 1.0
+
+StackView {
+ id: root
+ focus: true
+
+ property int duration: 500
+
+ delegate: StackViewDelegate {
+
+ pushTransition: StackViewTransition {
+ PropertyAnimation {
+ target: enterItem;
+ property: "opacity";
+ from: 0
+ to: 1;
+ duration: root.duration
+ }
+ }
+
+ popTransition: StackViewTransition {
+ id: popTransition
+
+ PropertyAnimation {
+ target: exitItem
+ property: "opacity"
+ from: 1
+ to: 0
+ duration: root.duration
+ }
+ }
+ }
+
+ Item {
+ id: dummyitem
+ anchors.fill: parent
+ //visible: false
+ }
+
+ Shortcut {
+ context: Qt.ApplicationShortcut
+ sequence: StandardKey.Cancel
+ onActivated: { root.pop(null) }
+ }
+
+ Connections {
+ target: ApplicationManagerInterface
+
+ onApplicationSurfaceReady: {
+ root.push(item)
+ }
+
+ onReleaseApplicationSurface: {
+ root.pop(null)
+ }
+ }
+}
diff --git a/CenterConsole/sysui/Launcher/CalendarWidget.qml b/CenterConsole/sysui/Launcher/CalendarWidget.qml
new file mode 100644
index 0000000..83f360f
--- /dev/null
+++ b/CenterConsole/sysui/Launcher/CalendarWidget.qml
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+import controls 1.0
+
+LaunchItemBackground {
+ text: "Calendar"
+ applicationName: "com.qtcompany.calendar"
+}
diff --git a/CenterConsole/sysui/Launcher/CarInfoWidget.qml b/CenterConsole/sysui/Launcher/CarInfoWidget.qml
new file mode 100644
index 0000000..34af49b
--- /dev/null
+++ b/CenterConsole/sysui/Launcher/CarInfoWidget.qml
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import controls 1.0
+import utils 1.0
+
+LaunchItemBackground {
+ text: "Car Info"
+ applicationName: "com.qtcompany.carinfo"
+
+ Image {
+ source: Style.symbol("car-info")
+ anchors.centerIn: parent
+ }
+}
diff --git a/CenterConsole/sysui/Launcher/ContactsWidget.qml b/CenterConsole/sysui/Launcher/ContactsWidget.qml
new file mode 100644
index 0000000..248158c
--- /dev/null
+++ b/CenterConsole/sysui/Launcher/ContactsWidget.qml
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import utils 1.0
+import controls 1.0
+
+LaunchItemBackground {
+ text: "Contacts"
+ applicationName: "com.qtcompany.contacts"
+ Image {
+ source: Style.symbol("contacts")
+ anchors.centerIn: parent
+ }
+}
diff --git a/CenterConsole/sysui/Launcher/LauncherBar.qml b/CenterConsole/sysui/Launcher/LauncherBar.qml
new file mode 100644
index 0000000..773dd1f
--- /dev/null
+++ b/CenterConsole/sysui/Launcher/LauncherBar.qml
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+import utils 1.0
+import QtApplicationManager 1.0
+
+Item {
+ id: root
+
+ width: Style.screenWidth
+ height: Style.launchBarHeight
+
+ MusicWidget {
+ id: musicWidget
+ anchors.margins: Style.padding
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: Style.paddingXXL
+ width: Style.launchBarHeight
+ height: root.height
+ }
+
+ CalendarWidget {
+ id: calendarWidget
+ anchors.left: musicWidget.right
+ anchors.right: parent.right
+ anchors.top: parent.top
+ height: root.height / 2
+ width: Style.launchBarHeight
+ anchors.margins: Style.padding
+ anchors.rightMargin: Style.paddingXXL
+ }
+ Row {
+ anchors.left: musicWidget.right
+ anchors.top: calendarWidget.bottom
+ anchors.bottom: musicWidget.bottom
+ anchors.margins: Style.padding
+ spacing: Style.padding
+
+ ContactsWidget {
+ id: contactsWidget
+ width: 256
+ height: 226
+ }
+ CarInfoWidget {
+ width: 256
+ height: 226
+ }
+ }
+}
diff --git a/CenterConsole/sysui/Launcher/MusicWidget.qml b/CenterConsole/sysui/Launcher/MusicWidget.qml
new file mode 100644
index 0000000..7a97b69
--- /dev/null
+++ b/CenterConsole/sysui/Launcher/MusicWidget.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+import QtApplicationManager 1.0
+import controls 1.0
+import utils 1.0
+import controls 1.0
+
+LaunchItemBackground {
+ id: root
+ applicationName: "com.pelagicore.media"
+ Label {
+ id: title
+ z: 1
+ text: "Music & TV"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: Style.paddingXXL
+ }
+
+ Image {
+ id: image
+ anchors.fill: root
+ asynchronous: true
+ source: musicControl.currentTrack ? musicControl.currentCover : ""
+ }
+ Image {
+ source: Style.symbol("MusicOverlayGradient")
+ anchors.bottom: parent.bottom
+ }
+
+ ApplicationIPCInterface {
+ id: musicControl
+
+ property var currentTrack
+ property string currentCover: ""
+
+ property string currentTime: "00:00"
+ property string durationTime: "00:00"
+ property bool playing: false
+
+ signal previousTrack()
+ signal nextTrack()
+ signal play()
+ signal pause()
+
+ Component.onCompleted: {
+ ApplicationIPCManager.registerInterface(musicControl, "com.pelagicore.music.control",
+ {})
+ }
+ }
+
+ Behavior on scale {
+ NumberAnimation {}
+ }
+
+ Column {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: Style.padding
+ width: parent.width
+ spacing: Style.padding
+
+ Label {
+ width: parent.width - 20
+ anchors.horizontalCenter: parent.horizontalCenter
+ maximumLineCount: 2
+ text: musicControl.currentTrack ? musicControl.currentTrack.title : ""
+ font.pixelSize: Style.fontSizeL
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Label {
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: musicControl.currentTrack
+ ? qsTr('%1 / %2').arg(musicControl.currentTrack.artist).arg(musicControl.currentTrack.album)
+ : ""
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 120
+ spacing: 90
+ Tool {
+ name: "video-previous"
+ vspan: 2
+ onClicked: musicControl.previousTrack()
+ }
+ Tool {
+ vspan: 2
+ name: active ? "video-pause" : "video-play"
+ onClicked: active ? musicControl.pause() : musicControl.play()
+ active: musicControl.playing
+ }
+ Tool {
+ vspan: 2
+ name: "video-next"
+ onClicked: musicControl.nextTrack()
+ }
+ }
+}
diff --git a/CenterConsole/sysui/StatusBar/DateAndTime.qml b/CenterConsole/sysui/StatusBar/DateAndTime.qml
new file mode 100644
index 0000000..47039d2
--- /dev/null
+++ b/CenterConsole/sysui/StatusBar/DateAndTime.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.0
+import QtQuick.Layouts 1.0
+import utils 1.0
+import controls 1.0
+import service.valuesource 1.0
+
+UIElement {
+ id: root
+
+// hspan: 3
+// vspan: 2
+
+ RowLayout {
+ anchors.top: parent.top
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: Style.padding
+
+ Label {
+ id: date
+ property string timeFormat: "MMMM"
+ font.capitalization: Font.AllUppercase
+ text: Qt.formatDateTime(ValueSource.currentDate, timeFormat)
+ }
+ Label {
+ id: date2
+ property string timeFormat: "d"
+ text: Qt.formatDateTime(ValueSource.currentDate, timeFormat)
+ }
+ Label {
+ text: "|"
+ }
+ Label {
+ id: clock
+ font.capitalization: Font.AllUppercase
+ text: Qt.formatDateTime(new Date(), "hh:mm")
+ } }
+}
diff --git a/CenterConsole/sysui/StatusBar/StatusBar.qml b/CenterConsole/sysui/StatusBar/StatusBar.qml
new file mode 100644
index 0000000..80f2e92
--- /dev/null
+++ b/CenterConsole/sysui/StatusBar/StatusBar.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+import utils 1.0
+import controls 1.0
+import service.statusbar 1.0
+import service.settings 1.0
+
+Item {
+ id: root
+ width: Style.screenWidth
+ height: Style.statusBarHeight
+ z: 1
+ Image {
+ source: Style.symbol("SimpleBottomBackground")
+ anchors.fill: parent
+ }
+ Row {
+ id: indicatorTray
+ spacing: Style.paddingXL
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ anchors.verticalCenter: parent.verticalCenter
+ Repeater {
+ id: repeater
+ model: StatusBarService.indicators
+ delegate: Image {
+ source: Style.symbolXS(modelData.name)
+ }
+ }
+ }
+ Row {
+ width: root.width / 4
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 10
+ DateAndTime {}
+ }
+
+ Image {
+ id: driverImage
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ source: Style.symbol("john")
+ scale: 0.5
+ }
+}
diff --git a/Cluster/Cluster.pro b/Cluster/Cluster.pro
new file mode 100644
index 0000000..94871de
--- /dev/null
+++ b/Cluster/Cluster.pro
@@ -0,0 +1,8 @@
+include (../deployment.pri)
+TEMPLATE = subdirs
+
+SUBDIRS = plugins
+
+qml.files = qml images
+qml.path = $$TARGET_PATH_CLUSTER
+INSTALLS += qml
diff --git a/Cluster/images.qrc b/Cluster/images.qrc
new file mode 100644
index 0000000..29ff8df
--- /dev/null
+++ b/Cluster/images.qrc
@@ -0,0 +1,23 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/Icon_TurnLeft_OFF.png</file>
+ <file>images/Icon_TurnLeft_ON.png</file>
+ <file>images/MapLocation.png</file>
+ <file>images/Icon_LowBeam_OFF.png</file>
+ <file>images/Icon_LowBeam_ON.png</file>
+ <file>images/Icon_PositionLights_OFF.png</file>
+ <file>images/Icon_PositionLights_ON.png</file>
+ <file>images/Icon_SeatBelt_OFF.png</file>
+ <file>images/Icon_SeatBelt_ON.png</file>
+ <file>images/Icon_TyreMalfunction_OFF.png</file>
+ <file>images/Icon_TyreMalfunction_ON.png</file>
+ <file>images/Icon_Battery_OFF.png</file>
+ <file>images/Icon_Battery_ON.png</file>
+ <file>images/Icon_Coolant_OFF.png</file>
+ <file>images/Icon_Coolant_ON.png</file>
+ <file>images/Icon_Fuel_OFF.png</file>
+ <file>images/Icon_Fuel_ON.png</file>
+ <file>images/Icon_BulbFailure_OFF.png</file>
+ <file>images/Icon_BulbFailure_ON.png</file>
+ </qresource>
+</RCC>
diff --git a/Cluster/images/BackgroundGradient.png b/Cluster/images/BackgroundGradient.png
new file mode 100644
index 0000000..d7e3f8e
--- /dev/null
+++ b/Cluster/images/BackgroundGradient.png
Binary files differ
diff --git a/Cluster/images/BottomPanel.png b/Cluster/images/BottomPanel.png
new file mode 100644
index 0000000..7979b52
--- /dev/null
+++ b/Cluster/images/BottomPanel.png
Binary files differ
diff --git a/Cluster/images/Built_with_Qt_RGB_logo_white.png b/Cluster/images/Built_with_Qt_RGB_logo_white.png
new file mode 100644
index 0000000..5905362
--- /dev/null
+++ b/Cluster/images/Built_with_Qt_RGB_logo_white.png
Binary files differ
diff --git a/Cluster/images/Cluster8Gauges.png b/Cluster/images/Cluster8Gauges.png
new file mode 100644
index 0000000..2dd545d
--- /dev/null
+++ b/Cluster/images/Cluster8Gauges.png
Binary files differ
diff --git a/Cluster/images/Cluster8GaugesPlain.png b/Cluster/images/Cluster8GaugesPlain.png
new file mode 100644
index 0000000..314aeb4
--- /dev/null
+++ b/Cluster/images/Cluster8GaugesPlain.png
Binary files differ
diff --git a/Cluster/images/ClusterGaugeCenters.png b/Cluster/images/ClusterGaugeCenters.png
new file mode 100644
index 0000000..2d4720e
--- /dev/null
+++ b/Cluster/images/ClusterGaugeCenters.png
Binary files differ
diff --git a/Cluster/images/ClusterGaugeCentersPlain.png b/Cluster/images/ClusterGaugeCentersPlain.png
new file mode 100644
index 0000000..4cca83c
--- /dev/null
+++ b/Cluster/images/ClusterGaugeCentersPlain.png
Binary files differ
diff --git a/Cluster/images/Gauges_normal.png b/Cluster/images/Gauges_normal.png
new file mode 100644
index 0000000..43b6810
--- /dev/null
+++ b/Cluster/images/Gauges_normal.png
Binary files differ
diff --git a/Cluster/images/Icon_Battery_OFF.png b/Cluster/images/Icon_Battery_OFF.png
new file mode 100644
index 0000000..91b1bd1
--- /dev/null
+++ b/Cluster/images/Icon_Battery_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_Battery_ON.png b/Cluster/images/Icon_Battery_ON.png
new file mode 100644
index 0000000..576e48f
--- /dev/null
+++ b/Cluster/images/Icon_Battery_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_BulbFailure_OFF.png b/Cluster/images/Icon_BulbFailure_OFF.png
new file mode 100644
index 0000000..03a2f79
--- /dev/null
+++ b/Cluster/images/Icon_BulbFailure_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_BulbFailure_ON.png b/Cluster/images/Icon_BulbFailure_ON.png
new file mode 100644
index 0000000..fdfc866
--- /dev/null
+++ b/Cluster/images/Icon_BulbFailure_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_Coolant_OFF.png b/Cluster/images/Icon_Coolant_OFF.png
new file mode 100644
index 0000000..901933f
--- /dev/null
+++ b/Cluster/images/Icon_Coolant_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_Coolant_ON.png b/Cluster/images/Icon_Coolant_ON.png
new file mode 100644
index 0000000..c3d8f3e
--- /dev/null
+++ b/Cluster/images/Icon_Coolant_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_Fuel_OFF.png b/Cluster/images/Icon_Fuel_OFF.png
new file mode 100644
index 0000000..f278fd5
--- /dev/null
+++ b/Cluster/images/Icon_Fuel_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_Fuel_ON.png b/Cluster/images/Icon_Fuel_ON.png
new file mode 100644
index 0000000..43448a6
--- /dev/null
+++ b/Cluster/images/Icon_Fuel_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_LowBeam_OFF.png b/Cluster/images/Icon_LowBeam_OFF.png
new file mode 100644
index 0000000..e7dbed0
--- /dev/null
+++ b/Cluster/images/Icon_LowBeam_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_LowBeam_ON.png b/Cluster/images/Icon_LowBeam_ON.png
new file mode 100644
index 0000000..b949991
--- /dev/null
+++ b/Cluster/images/Icon_LowBeam_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_ParkingBrake_OFF.png b/Cluster/images/Icon_ParkingBrake_OFF.png
new file mode 100644
index 0000000..66940aa
--- /dev/null
+++ b/Cluster/images/Icon_ParkingBrake_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_ParkingBrake_ON.png b/Cluster/images/Icon_ParkingBrake_ON.png
new file mode 100644
index 0000000..d508c9b
--- /dev/null
+++ b/Cluster/images/Icon_ParkingBrake_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_PositionLights_OFF.png b/Cluster/images/Icon_PositionLights_OFF.png
new file mode 100644
index 0000000..b309832
--- /dev/null
+++ b/Cluster/images/Icon_PositionLights_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_PositionLights_ON.png b/Cluster/images/Icon_PositionLights_ON.png
new file mode 100644
index 0000000..8d77207
--- /dev/null
+++ b/Cluster/images/Icon_PositionLights_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_SeatBelt_OFF.png b/Cluster/images/Icon_SeatBelt_OFF.png
new file mode 100644
index 0000000..332e773
--- /dev/null
+++ b/Cluster/images/Icon_SeatBelt_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_SeatBelt_ON.png b/Cluster/images/Icon_SeatBelt_ON.png
new file mode 100644
index 0000000..1d33139
--- /dev/null
+++ b/Cluster/images/Icon_SeatBelt_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_TurnLeft_OFF.png b/Cluster/images/Icon_TurnLeft_OFF.png
new file mode 100644
index 0000000..e7812eb
--- /dev/null
+++ b/Cluster/images/Icon_TurnLeft_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_TurnLeft_ON.png b/Cluster/images/Icon_TurnLeft_ON.png
new file mode 100644
index 0000000..9b4d03e
--- /dev/null
+++ b/Cluster/images/Icon_TurnLeft_ON.png
Binary files differ
diff --git a/Cluster/images/Icon_TyreMalfunction_OFF.png b/Cluster/images/Icon_TyreMalfunction_OFF.png
new file mode 100644
index 0000000..3117bd7
--- /dev/null
+++ b/Cluster/images/Icon_TyreMalfunction_OFF.png
Binary files differ
diff --git a/Cluster/images/Icon_TyreMalfunction_ON.png b/Cluster/images/Icon_TyreMalfunction_ON.png
new file mode 100644
index 0000000..eee237d
--- /dev/null
+++ b/Cluster/images/Icon_TyreMalfunction_ON.png
Binary files differ
diff --git a/Cluster/images/SpeedometerNeedle.png b/Cluster/images/SpeedometerNeedle.png
new file mode 100644
index 0000000..90158b1
--- /dev/null
+++ b/Cluster/images/SpeedometerNeedle.png
Binary files differ
diff --git a/Cluster/images/status_battery_highlight.png b/Cluster/images/status_battery_highlight.png
new file mode 100644
index 0000000..62000d8
--- /dev/null
+++ b/Cluster/images/status_battery_highlight.png
Binary files differ
diff --git a/Cluster/images/status_battery_icon.png b/Cluster/images/status_battery_icon.png
new file mode 100644
index 0000000..ec2b397
--- /dev/null
+++ b/Cluster/images/status_battery_icon.png
Binary files differ
diff --git a/Cluster/images/status_washer_fluid_highlight.png b/Cluster/images/status_washer_fluid_highlight.png
new file mode 100644
index 0000000..8bbfe61
--- /dev/null
+++ b/Cluster/images/status_washer_fluid_highlight.png
Binary files differ
diff --git a/Cluster/images/status_washer_fluid_icon.png b/Cluster/images/status_washer_fluid_icon.png
new file mode 100644
index 0000000..4546977
--- /dev/null
+++ b/Cluster/images/status_washer_fluid_icon.png
Binary files differ
diff --git a/Cluster/images/welcomeview_passenger_icon.png b/Cluster/images/welcomeview_passenger_icon.png
new file mode 100644
index 0000000..e2f2078
--- /dev/null
+++ b/Cluster/images/welcomeview_passenger_icon.png
Binary files differ
diff --git a/Cluster/images/welcomeview_status_icon.png b/Cluster/images/welcomeview_status_icon.png
new file mode 100644
index 0000000..0a640ba
--- /dev/null
+++ b/Cluster/images/welcomeview_status_icon.png
Binary files differ
diff --git a/Cluster/images/welcomeview_trip_info_icon.png b/Cluster/images/welcomeview_trip_info_icon.png
new file mode 100644
index 0000000..32172f0
--- /dev/null
+++ b/Cluster/images/welcomeview_trip_info_icon.png
Binary files differ
diff --git a/Cluster/images/welcomeview_trip_route.png b/Cluster/images/welcomeview_trip_route.png
new file mode 100644
index 0000000..f7bafb9
--- /dev/null
+++ b/Cluster/images/welcomeview_trip_route.png
Binary files differ
diff --git a/Cluster/main.cpp b/Cluster/main.cpp
new file mode 100644
index 0000000..f02ea90
--- /dev/null
+++ b/Cluster/main.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//#ifdef QT_3DCORE_LIB
+//#include "scenehelper.h"
+//#endif
+//#include "gauge.h"
+//#include "qtiviclusterdata.h"
+
+#include <QtQml/QQmlApplicationEngine>
+#include <QtGui/QFont>
+#include <QtGui/QFontDatabase>
+#include <QtGui/QGuiApplication>
+#include <QtQuick/QQuickView>
+
+//#include "etcprovider.h"
+
+#ifdef STATIC
+#include <QtPlugin>
+#include <QQmlExtensionPlugin>
+
+Q_IMPORT_PLUGIN(QtQuick2Plugin)
+Q_IMPORT_PLUGIN(QtQuickScene3DPlugin)
+Q_IMPORT_PLUGIN(Qt3DQuick3DCorePlugin)
+Q_IMPORT_PLUGIN(Qt3DQuick3DRenderPlugin)
+Q_IMPORT_PLUGIN(QtIVIVehicleFunctionsPlugin)
+//Q_IMPORT_PLUGIN(QMultimediaDeclarativeModule)
+//Q_IMPORT_PLUGIN(QtIVIVehicleFunctionsPlugin)
+//Q_IMPORT_PLUGIN(QtIVICorePlugin)
+//Q_IMPROT_PLUGIN(QtMultimediaPlugin)
+#endif
+
+int main(int argc, char **argv)
+{
+ qputenv("QT_QPA_EGLFS_HIDECURSOR", "1");
+ qputenv("QT_QPA_EGLFS_DISABLE_INPUT","1");
+ qputenv("QT_QPA_EGLFS_INTEGRATION","eglfs_viv");
+ qputenv("FB_MULTI_BUFFER","2");
+ qputenv("QT_QPA_EGLFS_WIDTH","1280");
+ qputenv("QT_QPA_EGLFS_HEIGHT","480");
+ qputenv("QT_QPA_EGLFS_PHYSICAL_WIDTH","1280");
+ qputenv("QT_QPA_EGLFS_PHYSICAL_HEIGHT","480");
+ qputenv("QT_QPA_FONTDIR",".");
+
+#ifdef STATIC
+ qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_QtQuick2Plugin().instance())->registerTypes("QtQuick");
+ qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_QtQuickScene3DPlugin().instance())->registerTypes("QtQuick.Scene3D");
+ qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_Qt3DQuick3DCorePlugin().instance())->registerTypes("Qt3D.Core");
+ qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_Qt3DQuick3DRenderPlugin().instance())->registerTypes("Qt3D.Render");
+ //qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_QMultimediaDeclarativeModule().instance())->registerTypes("QtMultimedia");
+
+ //qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_QtIVICorePlugin().instance())->registerTypes("QtIVICore");
+ qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_QtIVIVehicleFunctionsPlugin().instance())->registerTypes("QtIVIVehicleFunctions");
+ //qobject_cast<QQmlExtensionPlugin*>(qt_static_plugin_QMultimediaDeclarativeModule().instance())->registerTypes("QtMultimedia");
+#endif
+ QGuiApplication app(argc, argv);
+
+ //QGuiApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
+ //QGuiApplication::setAttribute(Qt::AA_UseOpenGLES);
+
+ QFontDatabase::addApplicationFont(":/fonts/Lato-Bold.ttf");
+ QFontDatabase::addApplicationFont(":/fonts/Lato-Semibold.ttf");
+ int latoID = QFontDatabase::addApplicationFont(":/fonts/Lato-Regular.ttf");
+ QStringList loadedFontFamilies = QFontDatabase::applicationFontFamilies(latoID);
+ if (!loadedFontFamilies.empty()) {
+ QString fontName = loadedFontFamilies.at(0);
+ QGuiApplication::setFont(QFont(fontName));
+ } else {
+ qWarning("Error: fail to load Open Sans font");
+ }
+
+#ifdef QT_3DCORE_LIB
+// qmlRegisterType<SceneHelper>("Qt3D.Examples", 2, 0, "SceneHelper");
+#endif
+// qmlRegisterType<QtIVIClusterData>("ClusterDemoData", 1, 0, "ClusterData");
+// qmlRegisterType<Gauge>("ClusterDemo", 1, 0, "GaugeFiller");
+// qmlRegisterSingletonType(QUrl("qrc:/qml/ValueSource.qml"), "ClusterDemo", 1, 0, "ValueSource");
+
+ QQuickView view;
+
+// EtcProvider *provider = new EtcProvider();
+// provider->setBaseUrl(QUrl("qrc:///images/"));
+// view.engine()->addImageProvider("etc", provider);
+
+ view.setColor(QColor(Qt::black));
+ view.setWidth(1280);
+ view.setHeight(480);
+ //view.setResizeMode(QQuickView::SizeRootObjectToView);
+
+ view.setSource(QUrl("qrc:/qml/DashboardFrame.qml"));
+ view.show();
+ return app.exec();
+}
diff --git a/Cluster/plugins/gaugefiller/gauge.cpp b/Cluster/plugins/gaugefiller/gauge.cpp
new file mode 100644
index 0000000..419196f
--- /dev/null
+++ b/Cluster/plugins/gaugefiller/gauge.cpp
@@ -0,0 +1,264 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gauge.h"
+#include "gaugenode.h"
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgflatcolormaterial.h>
+#include <QtMath>
+
+Gauge::Gauge(QQuickItem *parent)
+ : QQuickItem(parent)
+ , m_value(0)
+ , m_angle(0)
+ , m_numVertices(128)
+ , m_fillWidth(10)
+ , m_radius(0)
+ , m_updateGeometry(true)
+ , m_lefttoright(true)
+ , m_minAngle(0)
+ , m_maxAngle(270)
+ , m_minValue(0)
+ , m_maxValue(240)
+ , m_doNotFill(false)
+ , m_color(QColor(255, 0, 0))
+ , arc_length(0)
+ , arc_dist_per_vertices(0)
+ , frontCutDeg(0.0)
+ , backCutDeg(0.0)
+ , frontCutRad(0.0)
+ , backCutRad(0.0)
+ , m_cutRad(0)
+{
+ setFlag(ItemHasContents, true);
+}
+
+Gauge::~Gauge()
+{
+}
+
+void Gauge::setValue(qreal value)
+{
+ if (m_value == value || value > m_maxValue || value < m_minValue)
+ return;
+
+ m_value = value;
+ updateValue();
+
+ emit valueChanged(value);
+ update();
+}
+
+void Gauge::setNumVertices(int numVertices)
+{
+ if (m_numVertices == numVertices)
+ return;
+
+ m_numVertices = numVertices;
+ emit numVerticesChanged(numVertices);
+ update();
+}
+
+void Gauge::setFillWidth(double fillWidth)
+{
+ if (m_fillWidth == fillWidth)
+ return;
+
+ m_fillWidth = fillWidth;
+ emit fillWidthChanged(m_fillWidth);
+ update();
+}
+
+void Gauge::setRadius(int radius)
+{
+ if (m_radius == radius)
+ return;
+
+ m_radius = radius;
+ emit radiusChanged(m_radius);
+ update();
+}
+
+void Gauge::setMinAngle(double minAngle)
+{
+ if (m_minAngle == minAngle)
+ return;
+
+ m_minAngle = minAngle;
+
+ backCutDeg = m_minAngle;
+ backCutRad = qDegreesToRadians(backCutDeg);
+
+ if (m_minAngle < m_maxAngle)
+ m_lefttoright = true;
+ else
+ m_lefttoright = false;
+
+ updateValue();
+
+ emit minAngleChanged(m_minAngle);
+ update();
+}
+
+void Gauge::setMaxAngle(double maxAngle)
+{
+ if (m_maxAngle == maxAngle)
+ return;
+
+ m_maxAngle = maxAngle;
+
+ if (m_minAngle < m_maxAngle)
+ m_lefttoright = true;
+ else
+ m_lefttoright = false;
+
+ updateValue();
+ emit maxAngleChanged(m_maxAngle);
+ update();
+}
+
+void Gauge::setMinValue(double minValue)
+{
+ if (m_minValue == minValue)
+ return;
+
+ m_minValue = minValue;
+ emit minValueChanged(m_minValue);
+ update();
+}
+
+void Gauge::setMaxValue(double maxValue)
+{
+ if (m_maxValue == maxValue)
+ return;
+
+ m_maxValue = maxValue;
+ emit maxValueChanged(m_maxValue);
+ update();
+}
+
+void Gauge::setDoNotFill(bool doNotFill)
+{
+ if (m_doNotFill == doNotFill)
+ return;
+
+ m_doNotFill = doNotFill;
+ emit doNotFillChanged(m_doNotFill);
+ update();
+}
+
+void Gauge::setColor(QColor color)
+{
+ if (m_color == color)
+ return;
+
+ m_color = color;
+ emit colorChanged(m_color);
+ update();
+}
+
+void Gauge::setUpdateGeometry(bool updateGeometry)
+{
+ if (m_updateGeometry == updateGeometry)
+ return;
+ m_updateGeometry = updateGeometry;
+
+ if (m_updateGeometry)
+ calcArc();
+ else
+ m_cutRad = calcValueAsRad(m_value);
+
+ update();
+}
+
+float Gauge::calcValueAsRad(qreal value)
+{
+ return qDegreesToRadians((m_minAngle + ((m_maxAngle - m_minAngle) / (m_maxValue - m_minValue))
+ * (value - m_minValue)) - 180.);
+}
+
+void Gauge::updateValue()
+{
+ if (m_updateGeometry)
+ calcArc();
+ else
+ m_cutRad = calcValueAsRad(m_value);
+}
+
+void Gauge::calcArc()
+{
+ backCutDeg = m_minAngle;
+ backCutRad = qDegreesToRadians(backCutDeg - 270);
+
+ if (m_updateGeometry) {
+ m_angle = ((m_maxAngle - m_minAngle) / (m_maxValue - m_minValue))
+ * (m_value - m_minValue);
+ } else {
+ m_angle = ((m_maxAngle - m_minAngle) / (m_maxValue - m_minValue))
+ * (m_maxValue - m_minValue);
+ }
+
+ arc_length = qDegreesToRadians(m_angle);
+ arc_dist_per_vertices = arc_length / m_numVertices;
+
+ emit angleChanged(m_angle);
+}
+
+QSGNode *Gauge::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ GaugeNode *n = static_cast<GaugeNode *>(oldNode);
+
+ if (!n)
+ n = new GaugeNode(m_numVertices, m_color, m_doNotFill);
+
+ n->setLeftToRight(m_lefttoright);
+ n->setColor(m_color);
+ n->setBoundingRect(boundingRect());
+ n->setUpdateGeometry(m_updateGeometry);
+ n->setDoNotFill(m_doNotFill);
+ n->setBackCutRad(backCutRad);
+ n->setRadius(m_radius);
+ n->setArcDistPerVert(arc_dist_per_vertices);
+ n->setNumVertices(m_numVertices);
+ n->setFillWidth(m_fillWidth);
+ if (!m_updateGeometry)
+ n->setCutRad(m_cutRad);
+ n->draw();
+ return n;
+}
+
+void Gauge::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ QQuickItem::geometryChanged(newGeometry, oldGeometry);
+ if (m_radius == 0)
+ setRadius(newGeometry.height() * 0.5);
+
+ calcArc();
+ update();
+}
diff --git a/Cluster/plugins/gaugefiller/gauge.h b/Cluster/plugins/gaugefiller/gauge.h
new file mode 100644
index 0000000..f75f23a
--- /dev/null
+++ b/Cluster/plugins/gaugefiller/gauge.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GAUGE_H
+#define GAUGE_H
+
+#include <QQuickItem>
+
+class Gauge : public QQuickItem
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged)
+ Q_PROPERTY(qreal angle READ angle NOTIFY angleChanged)
+ Q_PROPERTY(int numVertices READ numVertices WRITE setNumVertices NOTIFY numVerticesChanged)
+
+ Q_PROPERTY(bool updateGeometry READ updateGeometry WRITE setUpdateGeometry NOTIFY updateGeometryChanged)
+ Q_PROPERTY(double fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged)
+ Q_PROPERTY(int radius READ radius WRITE setRadius NOTIFY radiusChanged)
+
+ Q_PROPERTY(double minAngle READ minAngle WRITE setMinAngle NOTIFY minAngleChanged)
+ Q_PROPERTY(double maxAngle READ maxAngle WRITE setMaxAngle NOTIFY maxAngleChanged)
+
+ Q_PROPERTY(double minValue READ minValue WRITE setMinValue NOTIFY minValueChanged)
+ Q_PROPERTY(double maxValue READ maxValue WRITE setMaxValue NOTIFY maxValueChanged)
+
+ Q_PROPERTY(bool doNotFill READ doNotFill WRITE setDoNotFill NOTIFY doNotFillChanged)
+ Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
+
+public:
+ Gauge(QQuickItem *parent = 0);
+ ~Gauge();
+
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+
+ qreal value() const { return m_value; }
+ qreal angle() const { return m_angle; }
+ bool updateGeometry() const { return m_updateGeometry; }
+ int numVertices() const { return m_numVertices; }
+ double fillWidth() const { return m_fillWidth; }
+ int radius() const { return m_radius; }
+ double minAngle() const { return m_minAngle; }
+ double maxAngle() const { return m_maxAngle; }
+ double minValue() const { return m_minValue; }
+ double maxValue() const { return m_maxValue; }
+ bool doNotFill() const { return m_doNotFill; }
+ QColor color() const { return m_color; }
+
+ void setValue(qreal value);
+ void setNumVertices(int numVertices);
+ void setFillWidth(double fillWidth);
+ void setRadius(int radius);
+ void setMinAngle(double minAngle);
+ void setMaxAngle(double maxAngle);
+ void setMinValue(double minValue);
+ void setMaxValue(double maxValue);
+ void setDoNotFill(bool doNotFill);
+ void setColor(QColor color);
+ void setUpdateGeometry(bool updateGeometry);
+
+signals:
+ void valueChanged(qreal value);
+ void angleChanged(qreal angle);
+ void numVerticesChanged(int numVertices);
+ void fillWidthChanged(double fillWidth);
+ void radiusChanged(int radius);
+ void minAngleChanged(double minAngle);
+ void maxAngleChanged(double maxAngle);
+ void minValueChanged(double minValue);
+ void maxValueChanged(double maxValue);
+ void doNotFillChanged(bool doNotFill);
+ void colorChanged(QColor color);
+ void updateGeometryChanged(bool updateGeometry);
+
+public slots:
+
+private:
+ void calcArc();
+ float calcValueAsRad(qreal value);
+ void updateValue();
+
+private:
+ qreal m_value;
+ double m_angle;
+ int m_numVertices;
+ double m_fillWidth;
+ int m_radius;
+ bool m_updateGeometry;
+ bool m_lefttoright;
+
+ double m_minAngle;
+ double m_maxAngle;
+ double m_minValue;
+ double m_maxValue;
+
+ bool m_doNotFill;
+ QColor m_color;
+
+ //Internal
+ double arc_length;
+ double arc_dist_per_vertices;
+
+ double frontCutDeg;
+ double backCutDeg;
+
+ double frontCutRad;
+ double backCutRad;
+
+ float m_cutRad;
+};
+
+#endif // GAUGE_H
diff --git a/Cluster/plugins/gaugefiller/gaugefiller.pro b/Cluster/plugins/gaugefiller/gaugefiller.pro
new file mode 100644
index 0000000..01165c0
--- /dev/null
+++ b/Cluster/plugins/gaugefiller/gaugefiller.pro
@@ -0,0 +1,23 @@
+include (../../../deployment.pri)
+TEMPLATE = lib
+TARGET = clustergaugefillerplugin
+QT += qml quick
+CONFIG += qt plugin c++11
+
+TARGET = $$qtLibraryTarget($$TARGET)
+uri = com.qtcompany.clustergaugefiller
+
+SOURCES += \
+ plugin.cpp \
+ gauge.cpp \
+ gaugenode.cpp
+
+HEADERS += \
+ gauge.h
+
+OTHER_FILES = qmldir
+
+qmldir.files = qmldir
+qmldir.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+target.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+INSTALLS += target qmldir
diff --git a/Cluster/plugins/gaugefiller/gaugenode.cpp b/Cluster/plugins/gaugefiller/gaugenode.cpp
new file mode 100644
index 0000000..8b9703d
--- /dev/null
+++ b/Cluster/plugins/gaugefiller/gaugenode.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "gaugenode.h"
+
+#include <QtQuick/qsgnode.h>
+#include <QtQuick/qsgflatcolormaterial.h>
+#include <QtMath>
+
+#define EXTRAVERTICES 3
+
+GaugeNode::GaugeNode(const int &numVertices, const QColor &color = QColor(255, 0, 0),
+ const bool &doNotFill = false)
+ : QSGGeometryNode()
+ //Could be optimized more. If only geometry update used we do not need to map textured points.
+ //, m_geometry(QSGGeometry::defaultAttributes_Point2D(), numVertices+EXTRAVERTICES)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), numVertices+EXTRAVERTICES)
+ , m_material(nullptr)
+ , m_numVertices(numVertices)
+ , m_doNotFill(doNotFill)
+ , m_color(color)
+ , m_cutRad(0.0)
+ , m_updateGeometry(true)
+ , m_lefttoright(true)
+ , m_dirtyBits(0)
+{
+ initGeometry();
+}
+
+GaugeNode::~GaugeNode()
+{
+ if (m_material)
+ delete m_material;
+}
+
+void GaugeNode::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+ m_color = color;
+ m_dirtyBits |= QSGNode::DirtyMaterial;
+}
+
+void GaugeNode::setCutRad(const float &cutRad)
+{
+ if (m_cutRad == cutRad)
+ return;
+
+ m_cutRad = cutRad;
+ if (!m_updateGeometry)
+ m_dirtyBits |= QSGNode::DirtyMaterial;
+}
+
+void GaugeNode::setDoNotFill(const bool &doNotFill)
+{
+ if (m_doNotFill == doNotFill)
+ return;
+
+ m_doNotFill = doNotFill;
+
+ if (m_doNotFill)
+ m_geometry.setDrawingMode(GL_LINE_STRIP);
+ else
+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
+
+ m_dirtyBits |= QSGNode::DirtyGeometry;
+}
+
+void GaugeNode::setBackCutRad(const double &backCutRad)
+{
+ if (backCutRad == m_backCutRad)
+ return;
+
+ m_backCutRad = backCutRad;
+ m_dirtyBits |= QSGNode::DirtyGeometry;
+}
+
+void GaugeNode::setRadius(const double &radius)
+{
+ if (m_radius == radius)
+ return;
+
+ m_radius = radius;
+ m_dirtyBits |= QSGNode::DirtyGeometry;
+}
+
+void GaugeNode::setArcDistPerVert(const double &dist)
+{
+ if (dist == m_arc_dist_per_vertices)
+ return;
+ m_arc_dist_per_vertices = dist;
+ m_dirtyBits |= QSGNode::DirtyGeometry;
+}
+
+void GaugeNode::setNumVertices(const int &numVertices)
+{
+ if (numVertices == m_numVertices)
+ return;
+
+ m_numVertices = numVertices;
+ m_geometry.allocate(m_numVertices + 3);
+ m_dirtyBits |= QSGNode::DirtyGeometry;
+}
+
+void GaugeNode::setFillWidth(const double &fillWidth)
+{
+ if (m_fillWidth == fillWidth)
+ return;
+
+ m_fillWidth = fillWidth;
+ m_dirtyBits |= QSGNode::DirtyGeometry;
+}
+
+void GaugeNode::setBoundingRect(const QRectF &rect)
+{
+ if (rect.width() == m_width && rect.height() == m_height)
+ return;
+
+ m_height = rect.height();
+ m_width = rect.width();
+ setCenterPoint(rect.center());
+ m_dirtyBits |= QSGNode::DirtyGeometry;
+}
+
+void GaugeNode::setCenterPoint(const QPointF &center)
+{
+ m_center_x = center.x();
+ m_center_y = center.y();
+}
+
+void GaugeNode::setUpdateGeometry(const bool &updateGeometry)
+{
+ if (m_updateGeometry == updateGeometry)
+ return;
+
+ m_updateGeometry = updateGeometry;
+
+ if (m_material)
+ delete m_material;
+
+ if (m_updateGeometry) {
+ QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
+ m_material = static_cast<QSGMaterial *>(material);
+ material->setColor(m_color);
+ setMaterial(m_material);
+ } else {
+ QSGSimpleMaterial<GaugeState> *material = GaugeShader::createMaterial();
+ m_material = static_cast<QSGMaterial *>(material);
+ material->state()->color = m_color;
+ material->state()->cutRad = m_cutRad;
+ material->state()->leftToRight = m_lefttoright;
+ material->setFlag(QSGMaterial::Blending);
+ setMaterial(m_material);
+ }
+ m_dirtyBits |= QSGNode::DirtyMaterial;
+}
+
+void GaugeNode::setLeftToRight(const bool &ltr)
+{
+ if (m_lefttoright == ltr)
+ return;
+
+ m_lefttoright = ltr;
+ m_dirtyBits |= QSGNode::DirtyMaterial;
+}
+
+void GaugeNode::drawGeometryTexturePoint2D()
+{
+ QSGGeometry::TexturedPoint2D *vertices = m_geometry.vertexDataAsTexturedPoint2D();
+
+ double current_angle_rad = 0.0;
+ double currentRadius = m_radius;
+ double d_arc_point_x = m_center_x + (currentRadius - m_fillWidth) * cos(m_backCutRad);
+ double d_arc_point_y = m_center_y + (currentRadius - m_fillWidth) * sin(m_backCutRad);
+
+ vertices[0].set(d_arc_point_x, d_arc_point_y,
+ d_arc_point_x / m_width, d_arc_point_y / m_height);
+ d_arc_point_x = m_center_x + currentRadius * cos(m_backCutRad);
+ d_arc_point_y = m_center_y + currentRadius * sin(m_backCutRad);
+ vertices[1].set(d_arc_point_x, d_arc_point_y,
+ d_arc_point_x / m_width, d_arc_point_y / m_height);
+ d_arc_point_x = 0;
+ d_arc_point_y = 0;
+
+ for (int i = 0; i < m_numVertices; ++i) {
+ current_angle_rad = m_backCutRad + i * m_arc_dist_per_vertices + m_arc_dist_per_vertices;
+
+ if (i % 2 == 0)
+ currentRadius -= m_fillWidth;
+ else
+ currentRadius += m_fillWidth;
+
+ d_arc_point_x = m_center_x + currentRadius * cos(current_angle_rad);
+ d_arc_point_y = m_center_y + currentRadius * sin(current_angle_rad);
+ vertices[i + 2].set(d_arc_point_x, d_arc_point_y,
+ d_arc_point_x / m_width, d_arc_point_y / m_height);
+ }
+ d_arc_point_x = m_center_x + (currentRadius - m_fillWidth) * cos(current_angle_rad);
+ d_arc_point_y = m_center_y + (currentRadius - m_fillWidth) * sin(current_angle_rad);
+
+ vertices[m_numVertices + 2].set(d_arc_point_x, d_arc_point_y,
+ d_arc_point_x / m_width, d_arc_point_y / m_height);
+}
+
+void GaugeNode::drawMaterial()
+{
+ if (m_updateGeometry) {
+ static_cast<QSGFlatColorMaterial *>(m_material)->setColor(m_color);
+ } else {
+ GaugeState *s = static_cast<QSGSimpleMaterial<GaugeState> *>(m_material)->state();
+ s->color = m_color;
+ s->cutRad = m_cutRad;
+ s->leftToRight = m_lefttoright;
+ }
+}
+
+void GaugeNode::draw()
+{
+ if (m_dirtyBits == 0)
+ return;
+
+ if (m_dirtyBits.testFlag(QSGNode::DirtyGeometry))
+ drawGeometryTexturePoint2D();
+ if (m_dirtyBits.testFlag(QSGNode::DirtyMaterial))
+ drawMaterial();
+
+ markDirty(m_dirtyBits);
+ m_dirtyBits = 0;
+}
+
+//Could be used to optimize vertices if only geometry is changed
+void GaugeNode::drawGeometry()
+{
+ QSGGeometry::Point2D *vertices = m_geometry.vertexDataAsPoint2D();
+
+ double d_arc_point_x = 0.0;
+ double d_arc_point_y = 0.0;
+ double current_angle_rad = 0.0;
+ double currentRadius = m_radius;
+
+ vertices[0].set(m_center_x + (currentRadius - m_fillWidth) * cos(m_backCutRad), m_center_y
+ + (currentRadius - m_fillWidth) * sin(m_backCutRad));
+ vertices[1].set(m_center_x + currentRadius * cos(m_backCutRad), m_center_y
+ + currentRadius * sin(m_backCutRad));
+
+ for (int i = 0; i < m_numVertices; ++i) {
+ current_angle_rad = m_backCutRad + i * m_arc_dist_per_vertices + m_arc_dist_per_vertices;
+
+ if (i % 2 == 0)
+ currentRadius -= m_fillWidth;
+ else
+ currentRadius += m_fillWidth;
+
+ d_arc_point_x = m_center_x + currentRadius * cos(current_angle_rad);
+ d_arc_point_y = m_center_y + currentRadius * sin(current_angle_rad);
+ vertices[i + 2].set(d_arc_point_x, d_arc_point_y);
+ }
+
+ vertices[m_numVertices + 2].set(m_center_x + (currentRadius - m_fillWidth)
+ * cos(current_angle_rad), m_center_y
+ + (currentRadius - m_fillWidth) * sin(current_angle_rad));
+
+ markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial);
+}
+
+void GaugeNode::initGeometry()
+{
+ m_geometry.setLineWidth(1);
+ if (m_doNotFill)
+ m_geometry.setDrawingMode(GL_LINE_STRIP);
+ else
+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
+
+ setGeometry(&m_geometry);
+
+ QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
+ material->setColor(m_color);
+
+ m_material = static_cast<QSGMaterial *>(material);
+ setMaterial(m_material);
+}
diff --git a/Cluster/plugins/gaugefiller/gaugenode.h b/Cluster/plugins/gaugefiller/gaugenode.h
new file mode 100644
index 0000000..17e2a49
--- /dev/null
+++ b/Cluster/plugins/gaugefiller/gaugenode.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GAUGENODE_H
+#define GAUGENODE_H
+
+#include <QSGNode>
+#include <QSGSimpleMaterial>
+#include <QColor>
+
+struct GaugeState
+{
+ QColor color;
+ GLfloat cutRad;
+ bool leftToRight;
+
+ int compare(const GaugeState *other) const
+ {
+ const unsigned int c = color.rgba();
+ const unsigned int co = other->color.rgba();
+ return std::tie(c, cutRad) > std::tie(co, other->cutRad);
+ }
+};
+
+class GaugeShader : public QSGSimpleMaterialShader<GaugeState>
+{
+ QSG_DECLARE_SIMPLE_COMPARABLE_SHADER(GaugeShader, GaugeState)
+
+public:
+ const char *vertexShader() const {
+ return
+ "attribute highp vec4 aVertex; \n"
+ "attribute highp vec2 aTexCoord; \n"
+ "uniform highp mat4 qt_Matrix; \n"
+ "varying highp vec2 texCoord; \n"
+ "void main() { \n"
+ " gl_Position = qt_Matrix * aVertex; \n"
+ " texCoord = aTexCoord; \n"
+ "}";
+ }
+
+ const char *fragmentShader() const {
+ return
+ "uniform lowp float qt_Opacity; \n"
+ "uniform lowp vec4 color; \n"
+ "uniform highp float cutRad; \n"
+ "uniform lowp bool leftToRight; \n"
+ "varying highp vec2 texCoord; \n"
+ "void main() {\n"
+ " highp vec2 uv = vec2(.5 - texCoord.y, .5 - texCoord.x);\n"
+ " if (leftToRight ? (-atan(uv.y,uv.x) < cutRad) : (-atan(uv.y,uv.x) > cutRad)) {\n"
+ " gl_FragColor = color * qt_Opacity;\n"
+ " } else {\n"
+//debug color " gl_FragColor = vec4(0.,1.,0.,1.0);\n"
+ " gl_FragColor = vec4(0.,0.,0.,0.);\n"
+ " } \n"
+ "}\n";
+ }
+
+ QList<QByteArray> attributes() const
+ {
+ return QList<QByteArray>() << "aVertex" << "aTexCoord";
+ }
+
+ void updateState(const GaugeState *state, const GaugeState *)
+ {
+ program()->setUniformValue(id_color, state->color);
+ program()->setUniformValue(id_cutRad, state->cutRad);
+ program()->setUniformValue(id_leftToRight, state->leftToRight);
+ }
+
+ void resolveUniforms()
+ {
+ id_color = program()->uniformLocation("color");
+ id_cutRad = program()->uniformLocation("cutRad");
+ id_leftToRight = program()->uniformLocation("leftToRight");
+ }
+
+private:
+ int id_color;
+ int id_cutRad;
+ int id_leftToRight;
+};
+
+class GaugeNode : public QSGGeometryNode
+{
+public:
+ GaugeNode(const int &numVertices, const QColor &color, const bool &doNotFill);
+ ~GaugeNode();
+
+ void setColor(const QColor &color);
+ void setCutRad(const float &cutRad);
+
+ void setDoNotFill(const bool &doNotFill);
+
+ void setBackCutRad(const double &backCutRad);
+ void setRadius(const double &radius);
+ void setArcDistPerVert(const double &dist);
+ void setNumVertices(const int &numVertices);
+
+ void setFillWidth(const double &fillWidth);
+ void setBoundingRect(const QRectF &rect);
+ void setUpdateGeometry(const bool &updateGeometry);
+
+ void setLeftToRight(const bool &ltr);
+
+ void draw();
+
+private:
+ void initGeometry();
+ void setCenterPoint(const QPointF &center);
+
+ void drawGeometry();
+ void drawGeometryTexturePoint2D();
+ void drawMaterial();
+
+private:
+ QSGGeometry m_geometry;
+ QSGMaterial *m_material;
+ int m_numVertices;
+ bool m_doNotFill;
+ QColor m_color;
+ float m_cutRad;
+ double m_radius;
+ bool m_updateGeometry;
+ bool m_lefttoright;
+
+ qreal m_width;
+ qreal m_height;
+ double m_center_y;
+ double m_center_x;
+ double m_backCutRad;
+ double m_fillWidth;
+ double m_arc_dist_per_vertices;
+
+ DirtyState m_dirtyBits;
+};
+
+#endif // GAUGENODE_H
diff --git a/Cluster/plugins/gaugefiller/plugin.cpp b/Cluster/plugins/gaugefiller/plugin.cpp
new file mode 100644
index 0000000..e6732fd
--- /dev/null
+++ b/Cluster/plugins/gaugefiller/plugin.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtQml/qqmlextensionplugin.h>
+#include <qqml.h>
+#include "gauge.h"
+
+static QObject *clusterGaugeFillerSingletonFactory(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(scriptEngine)
+ Q_UNUSED(engine)
+
+ return new Gauge();
+}
+
+class HoundPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("com.qtcompany.clustergaugefiller"));
+ qmlRegisterType<Gauge>(uri, 1, 0, "GaugeFiller");
+ }
+};
+
+#include "plugin.moc"
diff --git a/Cluster/plugins/gaugefiller/qmldir b/Cluster/plugins/gaugefiller/qmldir
new file mode 100644
index 0000000..1416273
--- /dev/null
+++ b/Cluster/plugins/gaugefiller/qmldir
@@ -0,0 +1,2 @@
+module com.qtcompany.clustergaugefiller
+plugin clustergaugefillerplugin
diff --git a/Cluster/plugins/plugins.pro b/Cluster/plugins/plugins.pro
new file mode 100644
index 0000000..805b714
--- /dev/null
+++ b/Cluster/plugins/plugins.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+SUBDIRS = \
+ scenehelper \
+ gaugefiller
diff --git a/Cluster/plugins/scenehelper/plugin.cpp b/Cluster/plugins/scenehelper/plugin.cpp
new file mode 100644
index 0000000..7432456
--- /dev/null
+++ b/Cluster/plugins/scenehelper/plugin.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtQml/qqmlextensionplugin.h>
+#include <qqml.h>
+#include "scenehelper.h"
+
+static QObject *clusterSceneHelperSingletonFactory(QQmlEngine *engine, QJSEngine *scriptEngine)
+{
+ Q_UNUSED(scriptEngine)
+ Q_UNUSED(engine)
+
+ return new SceneHelper();
+}
+
+class HoundPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+public:
+ virtual void registerTypes(const char *uri)
+ {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("com.qtcompany.clusterscenehelper"));
+ qmlRegisterType<SceneHelper>(uri, 1, 0, "SceneHelper");
+ }
+};
+
+#include "plugin.moc"
diff --git a/Cluster/plugins/scenehelper/qmldir b/Cluster/plugins/scenehelper/qmldir
new file mode 100644
index 0000000..0c50858
--- /dev/null
+++ b/Cluster/plugins/scenehelper/qmldir
@@ -0,0 +1,2 @@
+module com.qtcompany.clusterscenehelper
+plugin clusterscenehelperplugin
diff --git a/Cluster/plugins/scenehelper/scenehelper.cpp b/Cluster/plugins/scenehelper/scenehelper.cpp
new file mode 100644
index 0000000..bd6291a
--- /dev/null
+++ b/Cluster/plugins/scenehelper/scenehelper.cpp
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "scenehelper.h"
+
+QObject *SceneHelper::findEntity(Qt3DRender::QSceneLoader *loader, const QString &name)
+{
+ // The QSceneLoader instance is a component of an entity. The loaded scene
+ // tree is added under this entity.
+ QVector<Qt3DCore::QEntity *> entities = loader->entities();
+
+ if (entities.isEmpty())
+ return 0;
+
+ // Technically there could be multiple entities referencing the scene loader
+ // but sharing is discouraged, and in our case there will be one anyhow.
+ Qt3DCore::QEntity *root = entities[0];
+
+ // The scene structure and names always depend on the asset.
+ return root->findChild<Qt3DCore::QEntity *>(name);
+}
+
+void SceneHelper::removeFromScene(Qt3DRender::QSceneLoader *loader, const QStringList &names)
+{
+ //qDebug() << __FUNCTION__ << names;
+ QVector<Qt3DCore::QEntity *> entities = loader->entities();
+
+ if (entities.isEmpty())
+ return;
+
+ Qt3DCore::QEntity *root = entities[0];
+
+ foreach (QString name, names) {
+ QObject *entity = root->findChild<Qt3DCore::QEntity *>(name);
+ entity->setParent(Q_NULLPTR);
+ }
+}
+
+void SceneHelper::addMaterials(Qt3DRender::QSceneLoader *loader,
+ Qt3DRender::QMaterial *material, QStringList names)
+{
+ //qDebug() << __FUNCTION__ << material << names;
+ QVector<Qt3DCore::QEntity *> entities = loader->entities();
+
+ if (entities.isEmpty())
+ return;
+
+ Qt3DCore::QEntity *root = entities[0];
+
+ addComponents(names, root, material);
+}
+
+void SceneHelper::addMaterial(Qt3DRender::QSceneLoader *loader,
+ Qt3DRender::QMaterial *material, QString name)
+{
+ //qDebug() << __FUNCTION__ << material << name;
+ QVector<Qt3DCore::QEntity *> entities = loader->entities();
+
+ //qDebug() << entities;
+
+ if (entities.isEmpty())
+ return;
+
+ Qt3DCore::QEntity *root = entities[0];
+
+ addComponent(name, root, material);
+}
+
+void SceneHelper::replaceMaterial(Qt3DRender::QSceneLoader *loader, const QString &name,
+ Qt3DRender::QMaterial *material)
+{
+ //qDebug() << __FUNCTION__ << "Element " << name << " to " << material;
+ QVector<Qt3DCore::QEntity *> entities = loader->entities();
+
+ if (entities.isEmpty())
+ return;
+
+ Qt3DCore::QEntity *root = entities[0];
+ Qt3DCore::QEntity *entity = root->findChild<Qt3DCore::QEntity *>(name);
+ if (entity) {
+ QVector<Qt3DCore::QComponent *> components = entity->components();
+ //qDebug() << components;
+ foreach (Qt3DCore::QComponent *comp, components) {
+ if (qobject_cast<Qt3DRender::QMaterial *>(comp)) {
+ //qDebug() << "removing material";
+ entity->removeComponent(comp);
+ break;
+ }
+ }
+ //qDebug() << "adding" << material;
+ entity->addComponent(material);
+ } else {
+ qWarning() << __FUNCTION__ << "MISSING ELEMENT " << name;
+ }
+}
+
+void SceneHelper::addComponents(QStringList &names, Qt3DCore::QEntity *root,
+ Qt3DRender::QMaterial *material)
+{
+ //qDebug() << __FUNCTION__ << material;
+ foreach (QString name, names) {
+ Qt3DCore::QEntity *entity = root->findChild<Qt3DCore::QEntity *>(name);
+ //qDebug() << "entity = " << entity << " name " << name;
+ if (entity) {
+ QVector<Qt3DCore::QComponent *> components = entity->components();
+ foreach (Qt3DCore::QComponent *comp, components) {
+ //qDebug() << " comp = " << comp;
+ if (qobject_cast<Qt3DRender::QMaterial *>(comp)) {
+ //qDebug() << " removing " << comp;
+ entity->removeComponent(comp);
+ break;
+ }
+ }
+ //qDebug() << " adding " << material;
+ entity->addComponent(material);
+ } else {
+ qWarning() << __FUNCTION__ << "MISSING ELEMENT " << name;
+ }
+ }
+}
+
+/*void SceneHelper::searchCamera(Qt3DRender::QSceneLoader *loader, const QString &name)
+{
+ QVector<Qt3DCore::QEntity *> entities = loader->entities();
+
+ if (entities.isEmpty())
+ return;
+
+ Qt3DCore::QEntity *root = entities[0];
+ Qt3DCore::QEntity *entity = root->findChild<Qt3DCore::QEntity *>(name);
+ //qDebug() << "Found entity " << entity;
+ QVector<Qt3DCore::QComponent *> components = entity->components();
+ foreach (Qt3DCore::QComponent *comp, components) {
+ //qDebug() << " comp " << comp;
+ if (qobject_cast<Qt3DRender::QCameraLens *>(comp)) {
+ Qt3DRender::QCameraLens *lens = qobject_cast<Qt3DRender::QCameraLens *>(comp);
+ //qDebug() << " lens.left = " << lens->left() << lens->property("lookAt");
+ }
+ }
+}*/
+
+void SceneHelper::addComponent(QString &name, Qt3DCore::QEntity *root,
+ Qt3DRender::QMaterial *material)
+{
+ //qDebug() << __FUNCTION__ << material;
+ Qt3DCore::QEntity *entity = root->findChild<Qt3DCore::QEntity *>(name);
+ //qDebug() << "entity = " << entity << " name " << name;
+ if (entity) {
+ QVector<Qt3DCore::QComponent *> components = entity->components();
+ foreach (Qt3DCore::QComponent *comp, components) {
+ //qDebug() << " comp = " << comp;
+ if (qobject_cast<Qt3DRender::QMaterial *>(comp)) {
+ //qDebug() << " removing " << comp;
+ entity->removeComponent(comp);
+ break;
+ }
+ }
+ //qDebug() << " adding " << material;
+ entity->addComponent(material);
+ } else {
+ qWarning() << __FUNCTION__ << "MISSING ELEMENT " << name;
+ }
+}
+
+void SceneHelper::addListEntry(const QVariant &list, QObject *entry)
+{
+ QQmlListReference ref = list.value<QQmlListReference>();
+ ref.append(entry);
+}
diff --git a/Cluster/plugins/scenehelper/scenehelper.h b/Cluster/plugins/scenehelper/scenehelper.h
new file mode 100644
index 0000000..ec5ead7
--- /dev/null
+++ b/Cluster/plugins/scenehelper/scenehelper.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SCENEHELPER_H
+#define SCENEHELPER_H
+
+#include <QResource>
+
+#include <Qt3DRender/QRenderAspect>
+#include <Qt3DRender/QSceneLoader>
+#include <Qt3DCore/QEntity>
+//#include <Qt3DRender/QCameraLens>
+#include <Qt3DRender/QMaterial>
+#include <Qt3DQuick/QQmlAspectEngine>
+#include <Qt3DCore/QComponent>
+#include <QtQml>
+
+class SceneHelper : public QObject
+{
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE QObject *findEntity(Qt3DRender::QSceneLoader *loader, const QString &name);
+ Q_INVOKABLE void addListEntry(const QVariant &list, QObject *entry);
+ Q_INVOKABLE void removeFromScene(Qt3DRender::QSceneLoader *loader, const QStringList &names);
+ Q_INVOKABLE void addMaterials(Qt3DRender::QSceneLoader *loader,
+ Qt3DRender::QMaterial *material, QStringList names);
+ Q_INVOKABLE void addMaterial(Qt3DRender::QSceneLoader *loader,
+ Qt3DRender::QMaterial *material, QString name);
+ Q_INVOKABLE void replaceMaterial(Qt3DRender::QSceneLoader *loader, const QString &name,
+ Qt3DRender::QMaterial *material);
+ //Q_INVOKABLE void searchCamera(Qt3DRender::QSceneLoader *loader, const QString &name);
+
+private:
+ void addComponents(QStringList &names, Qt3DCore::QEntity *root,
+ Qt3DRender::QMaterial *material);
+ void addComponent(QString &name, Qt3DCore::QEntity *root, Qt3DRender::QMaterial *material);
+};
+
+#endif // SCENEHELPER_H
diff --git a/Cluster/plugins/scenehelper/scenehelper.pro b/Cluster/plugins/scenehelper/scenehelper.pro
new file mode 100644
index 0000000..ca1cfde
--- /dev/null
+++ b/Cluster/plugins/scenehelper/scenehelper.pro
@@ -0,0 +1,22 @@
+include (../../../deployment.pri)
+TEMPLATE = lib
+TARGET = clusterscenehelperplugin
+QT += qml quick 3dcore 3dextras 3drender 3dquick 3dquick-private
+CONFIG += qt plugin c++11
+
+TARGET = $$qtLibraryTarget($$TARGET)
+uri = com.qtcompany.clusterscenehelper
+
+SOURCES += \
+ plugin.cpp \
+ scenehelper.cpp
+
+HEADERS += \
+ scenehelper.h
+
+OTHER_FILES = qmldir
+
+qmldir.files = qmldir
+qmldir.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+target.path = $$TARGET_PATH/qml/$$replace(uri, \\., /)
+INSTALLS += target qmldir
diff --git a/Cluster/qml/BottomPanel.qml b/Cluster/qml/BottomPanel.qml
new file mode 100644
index 0000000..c6c5681
--- /dev/null
+++ b/Cluster/qml/BottomPanel.qml
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+
+Item {
+ property int iconMargin: 10
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: bottomPanelImage.width
+ height: bottomPanelImage.height
+
+ Image {
+ id: bottomPanelImage
+ source: "../images/BottomPanel.png"
+ }
+
+ TurnIndicator {
+ direction: Qt.LeftArrow
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 250
+ active: ValueSource.turnSignal & Qt.LeftArrow
+ }
+
+ Image {
+ id: iconCoolant
+ source: ValueSource.engineTemperature >= 100.0 ? "../images/Icon_Coolant_ON.png"
+ : "../images/Icon_Coolant_OFF.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.right: iconBattery.left
+ }
+
+ Image {
+ id: iconBattery
+ source: ValueSource.batteryLevel <= 25.0 ? "../images/Icon_Battery_ON.png"
+ : "../images/Icon_Battery_OFF.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.right: iconFuel.left
+ }
+
+ Image {
+ id: iconFuel
+ source: ValueSource.fuelLevel <= 20.0 ? "../images/Icon_Fuel_ON.png"
+ : "../images/Icon_Fuel_OFF.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.right: iconParkingBrake.left
+ }
+
+ Image {
+ id: iconParkingBrake
+ source: ValueSource.parkingBrake ? "../images/Icon_ParkingBrake_ON.png"
+ : "../images/Icon_ParkingBrake_OFF.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.right: textTime.left
+ anchors.rightMargin: 5
+ }
+
+ Text {
+ id: textTime
+ text: ValueSource.time
+ font.pixelSize: 24 //18
+ color: "white"
+ anchors.centerIn: parent
+ }
+
+ Image {
+ id: iconLowbeam
+ source: ValueSource.lowBeam ? "../images/Icon_LowBeam_ON.png"
+ : "../images/Icon_LowBeam_OFF.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.left: textTime.right
+ anchors.leftMargin: iconMargin
+ }
+
+ Image {
+ id: iconTyre
+ source: ValueSource.flatTire ? "../images/Icon_TyreMalfunction_ON.png"
+ : "../images/Icon_TyreMalfunction_OFF.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.left: iconLowbeam.right
+ }
+
+ Image {
+ id: iconLamp
+ source: ValueSource.lightFailure ? "../images/Icon_BulbFailure_ON.png"
+ : "../images/Icon_BulbFailure_OFF.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.left: iconTyre.right
+ }
+
+ Image {
+ id: iconSeatbelt
+ //source: ValueSource.seatBelt ? "../images/Icon_SeatBelt_ON.png"
+ // : "../images/Icon_SeatBelt_OFF.png"
+ source: "../images/Icon_SeatBelt_ON.png"
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.left: iconLamp.right
+ }
+
+ TurnIndicator {
+ direction: Qt.RightArrow
+ anchors.verticalCenter: textTime.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 250
+ active: ValueSource.turnSignal & Qt.RightArrow
+ }
+}
diff --git a/Cluster/qml/CarModel.qml b/Cluster/qml/CarModel.qml
new file mode 100644
index 0000000..b553461
--- /dev/null
+++ b/Cluster/qml/CarModel.qml
@@ -0,0 +1,551 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt3D.Core 2.0
+import Qt3D.Render 2.0
+import Qt3D.Extras 2.0
+import QtQuick 2.7 as Quick
+import com.qtcompany.clusterscenehelper 1.0
+
+Entity
+{
+ id: carModelEntity
+
+ property bool isReady: false
+ property bool hidden: true
+ property int width
+ property int height
+ property real carRotation: -30.0
+ property var previousComponent: undefined
+ property var previousMaterial
+ property vector3d defaultCameraPosition: Qt.vector3d(0.0, 5.0, 25.0)
+ property vector3d defaultLightPosition: Qt.vector3d(0.0, 20.0, 20.0)
+ property vector3d lightPosition: defaultLightPosition
+ property vector3d cameraPos: defaultCameraPosition
+ property vector3d lightPos: defaultLightPosition
+
+ property vector3d welcomeEndPosition: Qt.vector3d(-5.0, 5.0, 25.0)
+ property vector3d lightEndPosition: Qt.vector3d(20.0, 40.0, -10.0)
+ property vector3d statusEndPosition: Qt.vector3d(0.0, 40.0, 1.0)
+
+ property real lightPosMultiplier: 1.75
+
+ property int door_left: 1
+ property int door_right: 2
+ property int door_trunk: 4
+ property int door_hood: 8
+
+ property bool highlighting: false
+ property bool doorAction: false
+
+ property int highlightType: 0
+ property int defaultHighlight: 99
+
+ // Preset camera positions for highlights
+ // Light positions can use the same vectors, but with a multiplier to move it further or closer
+ // Lamp highlights
+ property vector3d positionFrontLeftHigh: Qt.vector3d(5.0, 4.0, 15.0) // Left headlight
+ property vector3d positionFrontRightHigh: Qt.vector3d(-5.0, 4.0, 15.0) // Right headlight
+ property vector3d positionFrontLeftLow: Qt.vector3d(3.0, 2.0, 15.0) // Left day light
+ property vector3d positionFrontRightLow: Qt.vector3d(-3.0, 2.0, 15.0) // Right day light
+ property vector3d positionRearLeft: Qt.vector3d(5.0, 5.0, -15.0) // Left tail light
+ property vector3d positionRearRight: Qt.vector3d(-5.0, 5.0, -15.0) // Right tail light
+ // Tire highlights
+ property vector3d positionLeftRear: Qt.vector3d(10.0, 2.0, -12.5)
+ property vector3d positionLeftFront: Qt.vector3d(10.0, 2.0, 12.5)
+ property vector3d positionRightRear: Qt.vector3d(-10.0, 2.0, -12.5)
+ property vector3d positionRightFront: Qt.vector3d(-10.0, 2.0, 12.5)
+ // Door highlights
+ property vector3d positionLeft: Qt.vector3d(35.0, 10.0, 0.0) // Doors on the left
+ property vector3d positionRight: Qt.vector3d(-35.0, 10.0, 0.0) // Doors on the right
+ property vector3d positionTop: Qt.vector3d(0.0, 40.0, 1.0) // Doors on both sides
+ property vector3d positionBack: Qt.vector3d(0.0, 20.0, -20.0) // Trunk
+ property vector3d positionFront: Qt.vector3d(0.0, 20.0, 20.0) // Hood
+
+ property color defaultBodyColor: "white"//Qt.rgba(0.5270588, 0.03137255, 0.03137255, 1.0)
+
+ property int topViewAnimationDuration: 2500
+
+ Camera {
+ id: cameraCar
+ projectionType: CameraLens.PerspectiveProjection
+ fieldOfView: 45
+ aspectRatio: carModelEntity.width / carModelEntity.height
+ nearPlane: 0.1
+ farPlane: 100.0
+ position: defaultCameraPosition
+ upVector: Qt.vector3d(0.0, 1.0, 0.0)
+ viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
+ }
+
+ Entity {
+ components: [
+ Transform {
+ translation: lightPosition
+ },
+ PointLight {
+ color: "white"
+ intensity: 1.0
+ }
+ ]
+ }
+
+ RenderSettings {
+ activeFrameGraph: TechniqueFilter {
+ matchAll: [ FilterKey { name: "renderingStyle"; value: "forward" } ]
+ id: carFramegraph
+
+ RenderSurfaceSelector {
+ id: surfaceSelector
+ Viewport {
+ normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
+
+ CameraSelector {
+ camera: cameraCar
+ NoDraw {
+ enabled: hidden
+ }
+ FrustumCulling {
+ ClearBuffers {
+ clearColor: "transparent"
+ buffers : ClearBuffers.ColorDepthBuffer
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Materials for the parts that need highlighting
+ PhongMaterial {
+ id: bodyMaterial
+ ambient: "black"
+ diffuse: defaultBodyColor
+ specular: Qt.rgba(0.7686275, 0.6196079, 0.3568628, 1.0)
+ shininess: 164
+ }
+
+ PhongMaterial {
+ id: bodyMaterialHighlight
+ ambient: "black"
+ diffuse: "orange"
+ shininess: 164
+ }
+
+ PhongMaterial {
+ id: tireMaterial
+ ambient: Qt.rgba(0.05, 0.05, 0.05, 1.0)
+ specular: Qt.rgba(0.594, 0.594, 0.594, 1.0)
+ diffuse: "black"
+ shininess: 51
+ }
+
+ PhongMaterial {
+ id: tireMaterialHighlight
+ ambient: "orange"
+ specular: Qt.rgba(0.594, 0.594, 0.594, 1.0)
+ diffuse: "black"
+ shininess: 51
+ }
+
+ DiffuseMapMaterial {
+ id: lampsMaterial
+ ambient: Qt.rgba(0.3, 0.3, 0.3, 1.0)
+ specular: Qt.rgba(0.279, 0.279, 0.279, 1.0)
+ diffuse: "models/Map11.jpg"
+ shininess: 31
+ }
+
+ // bodyMaterialHighlight is used for lamp highlight
+
+ // Materials for the parts that do not otherwise work correctly
+ Material {
+ id: transparentGlassMaterial
+
+ parameters: [
+ Parameter { name: "alpha"; value: 0.95 },
+ Parameter { name: "ka"; value: Qt.vector3d(0.0, 0.0, 0.0) },
+ Parameter { name: "kd"; value: Qt.vector3d(0.1608937, 0.16512, 0.154057) },
+ Parameter { name: "ks"; value: Qt.vector3d(1.0, 1.0, 1.0) },
+ Parameter { name: "shininess"; value: 33 }
+ ]
+
+ effect: DefaultAlphaEffect {
+ sourceRgbArg: BlendEquationArguments.SourceColor
+ destinationRgbArg: BlendEquationArguments.OneMinusSourceColor
+ }
+ }
+
+// PhongAlphaMaterial {
+// id: transparentGlassMaterial
+// diffuse: Qt.rgba(0.1608937, 0.16512, 0.154057, 1.0)
+// specular: Qt.rgba(1.0, 1.0, 1.0, 1.0)
+// alpha: 0.75
+// shininess: 33
+// }
+
+ PhongMaterial {
+ id: interiorMaterial
+ ambient: "black"
+ diffuse: Qt.rgba(0.17, 0.17, 0.18, 1.0)
+ shininess: 10
+ }
+
+ SceneHelper {
+ id: sceneHelper
+ }
+
+ Entity {
+ Transform {
+ id: scenePosition
+ matrix: {
+ var m = Qt.matrix4x4()
+ m.scale(1.15)
+ return m
+ }
+ }
+
+ Entity {
+ id: carModel
+
+ Transform {
+ id: carTransform
+ matrix: {
+ var m = Qt.matrix4x4()
+ m.rotate(carRotation, Qt.vector3d(0, 1, 0))
+ m.rotate(-90, Qt.vector3d(1, 0, 0))
+ return m
+ }
+ }
+
+ SceneLoader {
+ id: modelLoader
+ source: "models/sportscar.qgltf"
+ property var lampParts: [ "headlight_right", "headlight_left", "daylight_right",
+ "daylight_left", "taillight_left", "taillight_right" ]
+ property var bodyParts: [ "body", "door_left", "door_right",
+ "trunk", "hood" ]
+ property var transparentGlassParts: [ "d_glass" ]
+ property var tireParts: [ "tire_front_left", "tire_front_right",
+ "tire_rear_left", "tire_rear_right" ]
+ property var interiorParts: [ "interior" ]
+
+ // Note: If there are problems with transparent materials etc. check that you have
+ // exported the Collada file used to create the qgltf binary files using the following
+ // options in Blender (in Collada options category):
+ // - Triangulate (off)
+ // - Use Object Instances (on)
+ // - Sort by Object name (on)
+ // If just setting those is not enough, try changing the object names so that the
+ // object will be loaded in a different order.
+ // Use the following syntax for qgltf.exe:
+ // qgltf.exe file.dae -b -S
+
+ onStatusChanged: {
+ if (status === SceneLoader.Ready) {
+ sceneHelper.addMaterials(modelLoader, bodyMaterial, bodyParts)
+ sceneHelper.addMaterials(modelLoader, transparentGlassMaterial,
+ transparentGlassParts)
+ sceneHelper.addMaterials(modelLoader, interiorMaterial, interiorParts)
+ // Comment out if running standalone..
+ sceneHelper.addMaterial(modelLoader, lampsMaterial, lampParts[0])
+ sceneHelper.addMaterial(modelLoader, lampsMaterial, lampParts[1])
+ sceneHelper.addMaterial(modelLoader, lampsMaterial, lampParts[2])
+ sceneHelper.addMaterial(modelLoader, lampsMaterial, lampParts[3])
+ sceneHelper.addMaterial(modelLoader, lampsMaterial, lampParts[4])
+ sceneHelper.addMaterial(modelLoader, lampsMaterial, lampParts[5])
+ // ..Comment out if running standalone
+ sceneHelper.addMaterials(modelLoader, tireMaterial, tireParts)
+ //floorPlane.enabled = true // Disable floor for now
+ }
+ }
+ }
+
+ components: [carTransform, modelLoader]
+ }
+
+ Entity {
+ id: floorPlane
+ enabled: false
+
+ DiffuseMapMaterial {
+ id: planeMaterial
+ ambient: Qt.rgba(0, 0, 0, 1.0)
+ specular: Qt.rgba(0, 0, 0, 1.0)
+ diffuse: "../images-optimized/SportCarFloorShadow.png"
+ }
+
+ Transform {
+ id: planeRotation
+ matrix: {
+ var m = Qt.matrix4x4()
+ m.rotate(carRotation, Qt.vector3d(0, 1, 0))
+ return m
+ }
+ }
+
+ PlaneMesh {
+ id: planeMesh
+ width: 70
+ height: 70
+ }
+
+ components: [planeMesh, planeMaterial, planeRotation]
+ }
+
+ components: [ scenePosition ]
+ }
+
+ function highlightItem(idx) {
+ carRotationAnimation.stop()
+ carResetRotationAnimation.start()
+ highlighting = true
+ var highlightComponent
+ var highlightMaterial
+ var originalMaterial
+
+ switch (idx) {
+ case 1:
+ highlightComponent = "tire_front_left"
+ highlightMaterial = tireMaterialHighlight
+ originalMaterial = tireMaterial
+ lightPos = positionLeftFront.times(lightPosMultiplier)
+ cameraPos = positionLeftFront
+ break
+ case 2:
+ highlightComponent = "tire_front_right"
+ highlightMaterial = tireMaterialHighlight
+ originalMaterial = tireMaterial
+ lightPos = positionRightFront.times(lightPosMultiplier)
+ cameraPos = positionRightFront
+ break
+ case 3:
+ highlightComponent = "tire_rear_right"
+ highlightMaterial = tireMaterialHighlight
+ originalMaterial = tireMaterial
+ lightPos = positionRightRear.times(lightPosMultiplier)
+ cameraPos = positionRightRear
+ break
+ case 4:
+ highlightComponent = "tire_rear_left"
+ highlightMaterial = tireMaterialHighlight
+ originalMaterial = tireMaterial
+ lightPos = positionLeftRear.times(lightPosMultiplier)
+ cameraPos = positionLeftRear
+ break
+ case 5:
+ highlightComponent = "headlight_left"
+ highlightMaterial = bodyMaterialHighlight
+ originalMaterial = lampsMaterial
+ lightPos = positionFrontLeftHigh.times(lightPosMultiplier)
+ cameraPos = positionFrontLeftHigh
+ break
+ case 6:
+ highlightComponent = "headlight_right"
+ highlightMaterial = bodyMaterialHighlight
+ originalMaterial = lampsMaterial
+ lightPos = positionFrontRightHigh.times(lightPosMultiplier)
+ cameraPos = positionFrontRightHigh
+ break
+ case 7:
+ highlightComponent = "daylight_right"
+ highlightMaterial = bodyMaterialHighlight
+ originalMaterial = lampsMaterial
+ lightPos = positionFrontRightLow.times(lightPosMultiplier)
+ cameraPos = positionFrontRightLow
+ break
+ case 8:
+ highlightComponent = "daylight_left"
+ highlightMaterial = bodyMaterialHighlight
+ originalMaterial = lampsMaterial
+ lightPos = positionFrontLeftLow.times(lightPosMultiplier)
+ cameraPos = positionFrontLeftLow
+ break
+ case 9:
+ highlightComponent = "taillight_left"
+ highlightMaterial = bodyMaterialHighlight
+ originalMaterial = lampsMaterial
+ lightPos = positionRearLeft.times(lightPosMultiplier)
+ cameraPos = positionRearLeft
+ break
+ case 10:
+ highlightComponent = "taillight_right"
+ highlightMaterial = bodyMaterialHighlight
+ originalMaterial = lampsMaterial
+ lightPos = positionRearRight.times(lightPosMultiplier)
+ cameraPos = positionRearRight
+ break
+ default:
+ lightPos = defaultLightPosition
+ cameraPos = defaultCameraPosition
+ }
+
+ if (previousComponent !== undefined)
+ sceneHelper.replaceMaterial(modelLoader, previousComponent, previousMaterial)
+
+ if (highlightComponent !== undefined)
+ sceneHelper.replaceMaterial(modelLoader, highlightComponent, highlightMaterial)
+
+ previousComponent = highlightComponent
+ previousMaterial = originalMaterial
+ }
+
+ function highlightOpenDoors(openDoors) {
+ carRotationAnimation.stop()
+ carResetRotationAnimation.start()
+ highlighting = true
+ var openLeft = false
+ var openRight = false
+ var openBack = false
+ var openFront = false
+
+ // Check with bitwise operators, as they can be open in any combination
+ if (openDoors & door_left) {
+ sceneHelper.replaceMaterial(modelLoader, "door_left", bodyMaterialHighlight)
+ openLeft = true
+ } else {
+ sceneHelper.replaceMaterial(modelLoader, "door_left", bodyMaterial)
+ }
+
+ if (openDoors & door_right) {
+ sceneHelper.replaceMaterial(modelLoader, "door_right", bodyMaterialHighlight)
+ openRight = true
+ } else {
+ sceneHelper.replaceMaterial(modelLoader, "door_right", bodyMaterial)
+ }
+
+ if (openDoors & door_trunk) {
+ sceneHelper.replaceMaterial(modelLoader, "trunk", bodyMaterialHighlight)
+ openBack = true
+ } else {
+ sceneHelper.replaceMaterial(modelLoader, "trunk", bodyMaterial)
+ }
+
+ if (openDoors & door_hood) {
+ openFront = true
+ sceneHelper.replaceMaterial(modelLoader, "hood", bodyMaterialHighlight)
+ } else {
+ sceneHelper.replaceMaterial(modelLoader, "hood", bodyMaterial)
+ }
+
+ if (openRight && openLeft || openBack && openFront) {
+ lightPos = positionTop.times(0.5)
+ cameraPos = positionTop
+ } else if (openRight) {
+ lightPos = positionRight.times(0.33)
+ lightPos.y += 15.0
+ cameraPos = positionRight
+ } else if (openLeft) {
+ lightPos = positionLeft.times(0.33)
+ lightPos.y += 15.0
+ cameraPos = positionLeft
+ } else if (openBack) {
+ lightPos = positionBack.times(0.75)
+ cameraPos = positionBack
+ } else if (openFront) {
+ lightPos = positionFront.times(1.0)
+ cameraPos = positionFront
+ } else {
+ lightPos = defaultLightPosition
+ cameraPos = defaultCameraPosition
+ }
+ }
+
+ onCameraPosChanged: {
+ // Update both camera and light positions
+ cameraAnimation.to = cameraPos
+ lightAnimation.to = lightPos
+ cameraAnimation.restart()
+ lightAnimation.restart()
+ }
+
+ Quick.PropertyAnimation {
+ running: false
+ id: cameraAnimation
+ target: cameraCar
+ property: "position"
+ duration: topViewAnimationDuration
+ easing.type: Easing.InOutQuad
+ }
+
+ Quick.PropertyAnimation {
+ running: false
+ id: lightAnimation
+ target: carModelEntity
+ property: "lightPosition"
+ duration: topViewAnimationDuration * 4//1000
+ easing.type: Easing.Linear
+ }
+
+ Quick.RotationAnimation on carRotation {
+ id: carRotationAnimation
+ running: false
+ from: -30.0
+ to: 180.0
+ duration: topViewAnimationDuration
+ easing.type: Easing.InOutQuad
+ }
+
+ function resetHighlight() {
+ if (doorAction)
+ highlightOpenDoors(0)
+ else
+ highlightItem(defaultHighlight)
+ doorAction = false
+ }
+
+ function highlightLamp() {
+ highlightType = Math.floor(Math.random() * 6) + 5
+ highlightItem(highlightType)
+ return highlightType
+ }
+
+ function highlightTire() {
+ highlightType = Math.floor(Math.random() * 4) + 1
+ highlightItem(highlightType)
+ return highlightType
+ }
+
+ function startWelcomeAnimation() {
+ cameraAnimation.duration = 1000
+ cameraPos = welcomeEndPosition
+ idleTimer.restart()
+ }
+
+ Quick.Timer {
+ id: idleTimer
+ interval: 2000
+ onTriggered: {
+ cameraAnimation.duration = topViewAnimationDuration
+ lightPos = lightEndPosition
+ cameraPos = statusEndPosition
+ carRotationAnimation.restart()
+ }
+ }
+}
diff --git a/Cluster/qml/CenterView.qml b/Cluster/qml/CenterView.qml
new file mode 100644
index 0000000..0f4edda
--- /dev/null
+++ b/Cluster/qml/CenterView.qml
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import models 1.0
+import controls 1.0
+import utils 1.0
+
+Item {
+ anchors.fill: parent
+ property real defaultScale: 1.0
+ property var previousView: initialView
+
+ Image {
+ id: initialView
+ source: Style.symbol("john")
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: 400
+ }
+
+ Item {
+ id: musicContainer
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: 270
+ width: 354
+ height: 354
+ default property alias content: musiccontainer.children
+
+ Item {
+ id: musiccontainer
+ anchors.fill: parent
+ }
+ }
+
+ Item {
+ id: contactContainer
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: 350
+ width: 136
+ height: 250
+ default property alias content: contactcontainer.children
+
+ Item {
+ id: contactcontainer
+ anchors.fill: parent
+ }
+ }
+
+ Item {
+ id: carinfoContainer
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: 340
+ width: 265
+ height: 250
+ default property alias content: carinfocontainer.children
+
+ Item {
+ id: carinfocontainer
+ anchors.fill: parent
+ }
+ }
+
+ Item {
+ id: calendarContainer
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: 340
+ width: 220
+ height: 250
+ default property alias content: calendarcontainer.children
+
+ Item {
+ id: calendarcontainer
+ anchors.fill: parent
+ }
+ }
+
+ Connections {
+ target: ApplicationManagerInterface
+ onClusterWidgetReady: {
+ handleWidgetChange(category, item)
+ }
+ onClusterWidgetActivated: {
+ handleWidgetChange(category, item)
+ }
+ }
+
+ PropertyAnimation {
+ id: shrinkCenter
+ property: "scale"
+ to: 0.0
+ running: false
+ duration: 500
+ onStopped: {
+ target.visible = false
+ }
+ }
+
+ function handleWidgetChange(category, item) {
+ var container
+ if (category === "media")
+ container = musicContainer
+ else if (category === "contacts")
+ container = contactContainer
+ else if (category === "carinfo")
+ container = carinfoContainer
+ else if (category === "calendar")
+ container = calendarContainer
+ if (previousView !== container) {
+ // TODO: Find out why these commented-out animations cause flashing on HW, and fix it
+ //container.scale = defaultScale
+ container.visible = true
+ previousView.visible = false
+ //shrinkCenter.target = previousView
+ previousView = container
+ //shrinkCenter.start()
+ item.parent = container
+ container.content = item
+ item.width = container.width
+ item.height = container.height
+ }
+ }
+}
diff --git a/Cluster/qml/Dashboard.qml b/Cluster/qml/Dashboard.qml
new file mode 100644
index 0000000..260f989
--- /dev/null
+++ b/Cluster/qml/Dashboard.qml
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.7
+import service.valuesource 1.0
+import "gauges"
+
+Image
+{
+ id: dashboardEntity
+ // for static dashboard
+ source: "../images/Cluster8Gauges.png"
+ // for 2.5D lighting effect
+ //source: "../images/Cluster8GaugesPlain.png"
+ anchors.fill: parent
+
+ property bool parentVisible: parent.visible
+
+ property real timeScaleMultiplier: 1.0
+ property bool startupAnimationsFinished: false
+
+ property alias bottomPanelY: bottompanel.y
+ property alias needleRotation: tachometer.tachometerNeedleRotation
+
+ onNeedleRotationChanged: speedometer.speedometerNeedleRotation = needleRotation / 40.
+
+ //
+ // Fuelmeter
+ //
+ FuelMeter {}
+
+ //
+ // Batterymeter
+ //
+ BatteryMeter {}
+
+ //
+ // Consumptionmeter
+ //
+ ConsumptionMeter {}
+
+ //
+ // Temperaturemeter
+ //
+ TemperatureMeter {}
+
+ //
+ // Turbometer
+ //
+ TurboMeter {}
+
+ //
+ // Fpsmeter
+ //
+ FpsMeter {}
+
+ //
+ // Bottom Panel
+ //
+ BottomPanel {
+ id: bottompanel
+ y: 720
+ }
+
+ //
+ // Gauge center pieces
+ //
+ Image {
+ // for static dashboard
+ source: "../images/ClusterGaugeCenters.png"
+ // for 2.5D lighting effect
+ // source: "../images/ClusterGaugeCentersPlain.png"
+ anchors.fill: parent
+ }
+
+ // These two must be after center pieces, as they print text on top of the image
+
+ //
+ // Speedometer
+ //
+ SpeedoMeter {
+ id: speedometer
+ }
+
+ //
+ // Tachometer
+ //
+ TachoMeter {
+ id: tachometer
+ }
+
+ //
+ // 2.5D illusion for the 2.5D dashboard
+ //
+
+ // for speed-based effect
+ //property real speed: ValueSource.kph
+ //property int xlight: speed * 5
+ // for animated effect
+// property int xlight: -960
+// property int ylight: 0
+// property real angle: -10
+
+// ShaderEffect {
+// id: bumpShader
+// anchors.fill: parent
+// //property vector3d lightPos: Qt.vector3d(xlight, ylight, 0) // If using speed-based effect
+// property vector3d lightPos: Qt.vector3d(xlight, ylight, 0) // If using the animations below
+// property var source: ShaderEffectSource {
+// sourceItem: dashboardEntity
+// }
+// property var bump: Image {
+// source: "../images/Gauges_normal.png"
+// }
+// property real angle: dashboardEntity.angle * Math.PI / 180.0
+// fragmentShader:
+// "
+// uniform sampler2D source;
+// uniform sampler2D bump;
+// varying vec2 qt_TexCoord0;
+// uniform float qt_Opacity;
+// uniform vec3 lightPos;
+// uniform float angle;
+
+// highp vec3 dbModel(const highp vec3 norm)
+// {
+// // Transform position, normal, and tangent to eye coords
+// vec3 normal = vec3(0, 1, 0);
+// vec3 tangent = vec3(1, 0, -1);
+// vec3 position = vec3(960, -4000, 540);
+
+// // Calculate binormal vector
+// vec3 binormal = normalize(cross(normal, tangent));
+
+// // Construct matrix to transform from eye coords to tangent space
+// mat3 tangentMatrix = mat3 (
+// tangent.x, binormal.x, normal.x,
+// tangent.y, binormal.y, normal.y,
+// tangent.z, binormal.z, normal.z);
+
+// // Transform light direction and view direction to tangent space
+// vec3 s = lightPos - position;
+// vec3 lightDir = normalize(tangentMatrix * s);
+
+// vec3 v = -position;
+// vec3 viewDir = normalize(tangentMatrix * v);
+
+// float oldX = lightDir.x;
+// lightDir.x = (lightDir.x * cos(angle) - lightDir.z * sin(angle));
+// lightDir.z = (oldX * sin(angle) + lightDir.z * cos(angle));
+
+// vec3 ka = vec3(1.0, 1.0, 1.0);
+// vec3 ks = vec3(0.25, 0.25, 0.25);
+// float shininess = 50.0;
+
+// // Reflection of light direction about normal
+// vec3 r = reflect(-lightDir, norm);
+
+// vec3 diffuseColor = texture2D(source, qt_TexCoord0).rgb;
+
+// // Calculate the ambient contribution
+// vec3 ambient = ka * diffuseColor;
+
+// // Calculate the diffuse contribution
+// float sDotN = max(dot(lightDir, norm), 0.0);
+// vec3 diffuse = diffuseColor * sDotN;
+
+// // Calculate the specular highlight contribution
+// vec3 specular = vec3(0.0);
+// if (sDotN > 0.0)
+// specular = ks * pow(max(dot(r, viewDir), 0.0), shininess);
+
+// //return specular;
+// //return ambient;
+// //return ambient + diffuse;
+// return diffuse + specular;
+// //return ambient + specular;
+// //return ambient + diffuse + specular;
+// }
+
+// void main()
+// {
+// vec4 normal = 2.0 * texture2D(bump, qt_TexCoord0) - vec4(1.0);
+// vec3 result = dbModel(normalize(normal.xyz));
+// gl_FragColor = qt_Opacity * vec4(result, 1.0);
+// }
+// "
+// }
+
+// SequentialAnimation {
+// running: true
+// loops: Animation.Infinite
+// PropertyAnimation {
+// target: dashboardEntity
+// property: "xlight"
+// from: -960
+// to: 1920
+// duration: 15000
+// easing.type: Easing.InOutQuad
+// }
+// PropertyAnimation {
+// target: dashboardEntity
+// property: "xlight"
+// from: 1920
+// to: -960
+// duration: 15000
+// easing.type: Easing.InOutQuad
+// }
+// }
+
+ //
+ // Startup animations
+ //
+ SequentialAnimation {
+ id: speedometerStartupAnimations
+ running: false
+
+ SmoothedAnimation {
+ target: dashboardEntity
+ property: "bottomPanelY"
+ from: 720
+ to: 603
+ duration: 1000 * timeScaleMultiplier
+ easing.type: Easing.InCirc
+ }
+
+ SmoothedAnimation {
+ target: dashboardEntity
+ property: "needleRotation"
+ from: 0.0
+ to: -8000.0
+ duration: 1000 * timeScaleMultiplier
+ easing.type: Easing.InCubic
+ }
+
+ SmoothedAnimation {
+ target: dashboardEntity
+ property: "needleRotation"
+ from: -8000.0
+ to: 0.0
+ duration: 1000 * timeScaleMultiplier
+ easing.type: Easing.OutCubic
+ }
+
+ ScriptAction {
+ script: {
+ startupAnimationsFinished = true
+ ValueSource.startAnimations = true
+ }
+ }
+ }
+
+ // Just a hack for now; wait for the fader to finish
+ onParentVisibleChanged: {
+ if (visible)
+ initTimer.start()
+ }
+
+ Timer {
+ id: initTimer
+ running: false
+ interval: 1000
+ onTriggered: speedometerStartupAnimations.start()
+ }
+}
diff --git a/Cluster/qml/DashboardFrame.qml b/Cluster/qml/DashboardFrame.qml
new file mode 100644
index 0000000..24fc94c
--- /dev/null
+++ b/Cluster/qml/DashboardFrame.qml
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import Qt3D.Core 2.0
+
+Item {
+ id: root
+ width: 1920
+ height: 1080//720
+ anchors.top: parent.top
+
+ property real faderOpacity: 1.0
+
+ Loader {
+ id: welcomeLoader
+ source: "DashboardView.qml"
+ width: root.width
+ height: 720//root.height
+ onLoaded: {
+ initialFade.start()
+ }
+ }
+
+ property bool welcomeReady: welcomeLoader.status === Loader.Ready && welcomeLoader.item.isReady
+
+ onWelcomeReadyChanged: {
+ faderAnimation.start()
+ }
+
+ Loader {
+ id: dashLoader
+ source: "DashboardView.qml"
+ visible: false
+ active: true
+ width: root.width
+ height: 720//root.height
+ }
+
+ Rectangle {
+ id: fader
+ color: "black"
+ anchors.fill: root
+ opacity: faderOpacity
+ }
+
+ PropertyAnimation {
+ id: initialFade
+ target: root
+ property: "faderOpacity"
+ from: 1.0
+ to: 0.0
+ duration: 1000
+ }
+
+ SequentialAnimation {
+ id: faderAnimation
+ running: false
+
+ PropertyAnimation {
+ target: root
+ property: "faderOpacity"
+ from: 0.0
+ to: 1.0
+ duration: 500
+ }
+ ScriptAction {
+ script: {
+ welcomeLoader.visible = false
+ dashLoader.visible = true
+ }
+ }
+ PropertyAnimation {
+ target: root
+ property: "faderOpacity"
+ from: 1.0
+ to: 0.0
+ duration: 500
+ }
+ }
+
+ // Note: Use if cluster is displayed on 1080p screen
+ Rectangle {
+ color: "black"
+ anchors.bottom: parent.bottom
+ height: 360
+ width: 1920
+
+ Image {
+ source: "../images/Built_with_Qt_RGB_logo_white.png"
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.margins: 30
+ }
+ }
+}
diff --git a/Cluster/qml/DashboardView.qml b/Cluster/qml/DashboardView.qml
new file mode 100644
index 0000000..ced2387
--- /dev/null
+++ b/Cluster/qml/DashboardView.qml
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import utils 1.0
+
+Image
+{
+ id: dashboardEntity
+ source: "../images/BackgroundGradient.png"
+ width: 1920
+ height: 720
+
+ Dashboard {
+ id: dash
+ anchors.fill: parent
+ }
+
+ CenterView {
+ id: centerview
+ }
+
+ Component.onCompleted: Style.clusterWidgetReady = true
+}
diff --git a/Cluster/qml/FpsCounter.qml b/Cluster/qml/FpsCounter.qml
new file mode 100644
index 0000000..a98550e
--- /dev/null
+++ b/Cluster/qml/FpsCounter.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.6
+
+Item {
+ id: fpscounter
+ property real fpsNow: 0
+ property bool running: false
+ property alias fpsVisible: fpsLabel.visible
+ property int fpsInterval: 1000
+ property alias color: fpsLabel.color
+
+ Item {
+ id: swapTest
+ property real t
+ NumberAnimation on t {
+ running: fpscounter.running
+ from: 0
+ to: 1
+ duration: fpsInterval
+ loops: Animation.Infinite
+ }
+ onTChanged: {
+ ++fpsTimer.tick
+ }
+ }
+
+ Timer {
+ id: fpsTimer
+ running: fpscounter.running
+ repeat: true
+ interval: fpsInterval
+ property var lastFrameTime: new Date()
+ property int tick
+
+ onTriggered: {
+ var now = new Date()
+ var dt = now.getTime() - lastFrameTime.getTime()
+ lastFrameTime = now
+ var fps = (tick * fpsInterval) / dt
+ fpsNow = Math.round(fps * 10) / 10
+ tick = 0
+
+ if (fpsVisible)
+ fpsLabel.updateYerself()
+ }
+ }
+
+ Text {
+ id: fpsLabel
+ visible: false
+
+ anchors.centerIn: parent
+ font.pixelSize: 10
+ color: "white"
+
+ function updateYerself() {
+ text = Math.round(fpsNow)
+ }
+ }
+}
diff --git a/Cluster/qml/TurnIndicator.qml b/Cluster/qml/TurnIndicator.qml
new file mode 100644
index 0000000..71bba6d
--- /dev/null
+++ b/Cluster/qml/TurnIndicator.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.6
+
+Item {
+ property int direction: Qt.NoArrow
+ property bool active: false
+ property bool flashing: false
+
+ width: 47
+ height: 52
+
+ Timer {
+ id: flashTimer
+ interval: 500
+ running: (direction !== Qt.NoArrow)
+ repeat: true
+ onTriggered: flashing = !flashing
+ }
+
+ Image {
+ id: turnIndicatorImage
+ source: "../images/Icon_TurnLeft_ON.png"
+ anchors.fill: parent
+ mirror: direction === Qt.RightArrow
+ visible: active && flashing
+ }
+
+ Image {
+ source: "../images/Icon_TurnLeft_OFF.png"
+ anchors.fill: parent
+ mirror: direction === Qt.RightArrow
+ visible: !turnIndicatorImage.visible
+ }
+}
diff --git a/Cluster/qml/WelcomeDriver.qml b/Cluster/qml/WelcomeDriver.qml
new file mode 100644
index 0000000..7a4d601
--- /dev/null
+++ b/Cluster/qml/WelcomeDriver.qml
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import controls 1.0
+import utils 1.0
+
+Item {
+ anchors.fill: parent
+
+ property string welcomeText: "GOOD MORNING"
+
+ Column {
+ anchors.centerIn: parent
+ spacing: 10
+
+ Image {
+ id: driverImage
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: Style.symbol("john")
+ opacity: 0.0
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ }
+
+ Text {
+ id: driverText
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: welcomeText
+ font.bold: true
+ font.pixelSize: 20
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ opacity: 0.0
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ }
+
+ Text {
+ id: driverSecondRowText
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "John"
+ font.pixelSize: 30
+ color: "#EF2973"
+ horizontalAlignment: Text.AlignHCenter
+ opacity: 0.0
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ var currentDate = new Date()
+ var hours = currentDate.getHours()
+ if (hours > 0 && hours < 3)
+ welcomeText = "GOOD LATE EVENING"
+ else if (hours >= 3 && hours < 12)
+ welcomeText = "GOOD MORNING"
+ else if (hours >= 12 && hours < 18)
+ welcomeText = "GOOD AFTERNOON"
+ else if (hours >= 18 && hours < 24)
+ welcomeText = "GOOD EVENING"
+
+ driverText.opacity = 1.0
+ driverRecognition.start()
+ }
+
+ Timer {
+ id: driverRecognition
+ running: false
+ interval: 1000
+ onTriggered: {
+ driverImage.opacity = 1.0
+ driverSecondRowText.opacity = 1.0
+ }
+ }
+}
diff --git a/Cluster/qml/WelcomeInfoNote.qml b/Cluster/qml/WelcomeInfoNote.qml
new file mode 100644
index 0000000..0d63b9b
--- /dev/null
+++ b/Cluster/qml/WelcomeInfoNote.qml
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.7
+
+Column {
+ property alias firstline: tripInfoAmount.text
+ property alias firstlineunit: tripInfoUnit.text
+ property alias secondline: tripInfoText.text
+
+ spacing: 3
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 3
+
+ Text {
+ id: tripInfoAmount
+ text: "9:40"
+ font.pixelSize: 18
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ }
+
+ Text {
+ id: tripInfoUnit
+ text: "km"
+ font.pixelSize: 12
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignTop
+ }
+ }
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ id: tripInfoText
+ text: "Start time"
+ font.pixelSize: 12
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ }
+}
diff --git a/Cluster/qml/WelcomeStatus.qml b/Cluster/qml/WelcomeStatus.qml
new file mode 100644
index 0000000..379387d
--- /dev/null
+++ b/Cluster/qml/WelcomeStatus.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+
+Item {
+ anchors.fill: parent
+
+ Column {
+ anchors.centerIn: parent
+ spacing: 20
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 10
+
+ Image {
+ id: statusImage
+ source: "../images/welcomeview_status_icon.png"
+ }
+
+ Text {
+ id: statusText
+ anchors.verticalCenter: statusImage.verticalCenter
+ text: "READY FOR THE ROAD"
+ font.pixelSize: 18
+ color: "white"
+ }
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 20
+
+ Rectangle {
+ id: line
+ height: 2
+ width: 205
+ color: "gray"
+ }
+
+ Text {
+ text: "Status"
+ font.pixelSize: 18
+ color: "white"
+ anchors.verticalCenter: line.verticalCenter
+ }
+
+ Rectangle {
+ height: 2
+ width: 205
+ color: "gray"
+ }
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 50
+
+ WelcomeInfoNote {
+ firstline: ValueSource.totalDistance.toString()
+ firstlineunit: "KM"
+ secondline: "Total\ndistance"
+ }
+
+ WelcomeInfoNote {
+ firstline: ValueSource.kmSinceCharge.toString()
+ firstlineunit: "KM"
+ secondline: "Since last\ncharge"
+ }
+
+ WelcomeInfoNote {
+ firstline: ValueSource.avRangePerCharge.toString()
+ firstlineunit: "KM"
+ secondline: "Average\nrange/charge"
+ }
+
+ WelcomeInfoNote {
+ firstline: ValueSource.energyPerKm.toString()
+ firstlineunit: "WH"
+ secondline: "energy/km"
+ }
+ }
+
+ Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: 2
+ width: 500
+ color: "gray"
+ }
+ }
+}
diff --git a/Cluster/qml/WelcomeStatusNote.qml b/Cluster/qml/WelcomeStatusNote.qml
new file mode 100644
index 0000000..042f89b
--- /dev/null
+++ b/Cluster/qml/WelcomeStatusNote.qml
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.7
+
+Item {
+ property string position: "right"
+ property alias text: statusNoteText.text
+ property string icon
+ property string highlight
+
+ Column {
+ spacing: 5
+
+ Row {
+ id: statusNoteRow
+ spacing: 5
+
+ Image {
+ id: statusNotePointerImage
+ height: 66
+ fillMode: Image.Pad
+ source: position === "left" ? icon : highlight
+ anchors.verticalCenter: statusNoteImage.verticalCenter
+ }
+
+ Rectangle {
+ id: statusNoteLineImage
+ height: 2
+ width: 100
+ color: "gray"
+ anchors.verticalCenter: statusNoteImage.verticalCenter
+ }
+
+ Image {
+ id: statusNoteImage
+ height: 66
+ fillMode: Image.Pad
+ source: position === "right" ? icon : highlight
+ }
+ }
+
+ Text {
+ id: statusNoteText
+ anchors.right: position === "right" ? statusNoteRow.right : undefined
+ anchors.left: position === "left" ? statusNoteRow.left : undefined
+ style: Text.RichText
+ font.pixelSize: 14
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+}
diff --git a/Cluster/qml/WelcomeTripSummary.qml b/Cluster/qml/WelcomeTripSummary.qml
new file mode 100644
index 0000000..b9bb647
--- /dev/null
+++ b/Cluster/qml/WelcomeTripSummary.qml
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+
+Item {
+ anchors.fill: parent
+
+ Column {
+ anchors.centerIn: parent
+ spacing: 20
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 10
+
+ Image {
+ id: tripSummaryImage
+ source: "../images/welcomeview_trip_info_icon.png"
+ }
+
+ Text {
+ id: tripSummaryText
+ anchors.verticalCenter: tripSummaryImage.verticalCenter
+ text: "TRIP SUMMARY"
+ font.pixelSize: 18
+ color: "white"
+ }
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 50
+
+ WelcomeInfoNote {
+ firstline: "9:40"
+ secondline: "Start time"
+ }
+
+ WelcomeInfoNote {
+ firstline: "0:38"
+ secondline: "Duration"
+ }
+
+ WelcomeInfoNote {
+ firstline: "58"
+ firstlineunit: "KM"
+ secondline: "Distance"
+ }
+ }
+
+ Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: 2
+ width: 400
+ color: "gray"
+ }
+
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 50
+
+ WelcomeInfoNote {
+ firstline: "324"
+ firstlineunit: "WH"
+ secondline: "Average\nenergy/km"
+ }
+
+ WelcomeInfoNote {
+ firstline: "18.7"
+ firstlineunit: "KWH"
+ secondline: "Total energy"
+ }
+
+ WelcomeInfoNote {
+ firstline: "60"
+ firstlineunit: "KMH"
+ secondline: "Average\nspeed"
+ }
+ }
+
+ Image {
+ // TODO: Image from route?
+ anchors.horizontalCenter: parent.horizontalCenter
+ source: "../images/welcomeview_trip_route.png"
+ }
+ }
+}
diff --git a/Cluster/qml/WelcomeView.qml b/Cluster/qml/WelcomeView.qml
new file mode 100644
index 0000000..c1ade20
--- /dev/null
+++ b/Cluster/qml/WelcomeView.qml
@@ -0,0 +1,232 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Scene3D 2.0
+
+Image
+{
+ id: welcomeView
+ source: "../images/BackgroundGradient.png"
+ width: 1920
+ height: 720
+
+ property alias hidden: carModel.hidden
+ property bool isReady: false
+
+ Scene3D {
+ id: welcomeScene
+ width: welcomeView.width / 2
+ height: welcomeView.height
+ multisample: true
+
+ CarModel {
+ id: carModel
+ width: welcomeView.width
+ height: welcomeView.height
+ }
+ }
+
+ Rectangle {
+ id: infoPane
+ anchors.top: welcomeView.top
+ anchors.bottom: welcomeView.bottom
+ anchors.right: welcomeView.right
+ anchors.left: welcomeScene.right
+ color: "transparent"
+
+ Loader {
+ id: infoPaneLoader
+ anchors.fill: parent
+ source: "WelcomeDriver.qml"
+ active: true
+ }
+ }
+
+ Image {
+ id: passengerDriver
+ source: "../images/welcomeview_passenger_icon.png"
+ opacity: 0.0
+ scale: 2.0
+ x: 410
+ y: 330
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ Behavior on scale {
+ PropertyAnimation {
+ duration: 1000
+ easing.type: Easing.OutCubic
+ }
+ }
+ }
+
+ Image {
+ id: passengerShotgun
+ source: "../images/welcomeview_passenger_icon.png"
+ opacity: 0.0
+ scale: 2.0
+ x: 500
+ y: 330
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ Behavior on scale {
+ PropertyAnimation {
+ duration: 1000
+ easing.type: Easing.OutCubic
+ }
+ }
+ }
+
+ Image {
+ id: passengerRearLeft
+ source: "../images/welcomeview_passenger_icon.png"
+ opacity: 0.0
+ scale: 2.0
+ x: 415
+ y: 430
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ Behavior on scale {
+ PropertyAnimation {
+ duration: 1000
+ easing.type: Easing.OutCubic
+ }
+ }
+ }
+
+ Image {
+ id: passengerRearRight
+ source: "../images/welcomeview_passenger_icon.png"
+ opacity: 0.0
+ scale: 2.0
+ x: 495
+ y: 430
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ Behavior on scale {
+ PropertyAnimation {
+ duration: 1000
+ easing.type: Easing.OutCubic
+ }
+ }
+ }
+
+ WelcomeStatusNote {
+ id: washerFluidNote
+ text: "<center><font color=\"#FFFFFF\">Washer fluid<br>Low <font color=\"#EF2973\">10%"
+ icon: "../images/status_washer_fluid_icon.png"
+ highlight: "../images/status_washer_fluid_highlight.png"
+ position: "right"
+ opacity: 0.0
+ x: 535
+ y: 200
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ }
+
+ WelcomeStatusNote {
+ id: batteryLowNote
+ text: "<center><font color=\"#FFFFFF\">Battery low<br>Range <font color=\"#EF2973\">35KM"
+ icon: "../images/status_battery_icon.png"
+ highlight: "../images/status_battery_highlight.png"
+ position: "left"
+ opacity: 0.0
+ x: 205
+ y: 497
+ Behavior on opacity {
+ PropertyAnimation { duration: 1000 }
+ }
+ }
+
+ // Functions to control highlights from dashboard
+ function highlightLamp() {
+ var type = carModel.highlightLamp()
+ carModel.toggleIdleTimer(true)
+ resetModelTimer.restart()
+ return type
+ }
+
+ function highlightDoors(doors) {
+ doorAction = true
+ carModel.doorAction = true
+ carModel.highlightOpenDoors(doors)
+ carModel.toggleIdleTimer(true)
+ resetModelTimer.restart()
+ }
+
+ function highlightTire() {
+ var type = carModel.highlightTire()
+ carModel.toggleIdleTimer(true)
+ resetModelTimer.restart()
+ return type
+ }
+
+ Timer {
+ running: true
+ interval: 6000
+ onTriggered: {
+ infoPaneLoader.source = "WelcomeTripSummary.qml"
+ statusCheckTimer.start()
+ passengerDriver.opacity = 1.0
+ passengerRearRight.opacity = 1.0
+ passengerDriver.scale = 1.0
+ passengerRearRight.scale = 1.0
+ washerFluidNote.opacity = 1.0
+ batteryLowNote.opacity = 1.0
+ }
+ }
+
+ Timer {
+ id: statusCheckTimer
+ running: false
+ interval: 5000
+ onTriggered: {
+ infoPaneLoader.source = "WelcomeStatus.qml"
+ batteryLowNote.opacity = 0.0
+ readyTimer.start()
+ }
+ }
+
+ Component.onCompleted: {
+ carModel.startWelcomeAnimation()
+ }
+
+ Timer {
+ id: readyTimer
+ running: false
+ interval: 5000
+ onTriggered: {
+ isReady = true
+ }
+ }
+}
diff --git a/Cluster/qml/gauges/BatteryMeter.qml b/Cluster/qml/gauges/BatteryMeter.qml
new file mode 100644
index 0000000..d6380a9
--- /dev/null
+++ b/Cluster/qml/gauges/BatteryMeter.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+
+Item {
+ property real batterymeterNeedleRotation: -batteryValue * batteryDegreesPerValue
+ property real batteryValue: ValueSource.batteryLevel
+ property real maxValueAngle: 317
+ property real minValueAngle: 225
+ property real maximumValue: 100
+ property real batteryDegreesPerValue: Math.abs((maxValueAngle - minValueAngle) / maximumValue)
+
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.rightMargin: 654
+ anchors.topMargin: 140
+ width: 162
+ height: 10
+ rotation: batterymeterNeedleRotation - 135
+
+ Image {
+ width: 54
+ height: 5
+ //opacity: 0.75
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+}
diff --git a/Cluster/qml/gauges/ConsumptionMeter.qml b/Cluster/qml/gauges/ConsumptionMeter.qml
new file mode 100644
index 0000000..f2cbf39
--- /dev/null
+++ b/Cluster/qml/gauges/ConsumptionMeter.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.7
+import service.valuesource 1.0
+import com.qtcompany.clustergaugefiller 1.0
+
+Item {
+ property real consumptionValue: 2.0 + ValueSource.rpm / 444.45
+ property real minValueAngle: 378
+ property real maxValueAngle: 291
+ property real minimumValue: 0
+ property real maximumValue: 20
+
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.topMargin: 365
+ anchors.rightMargin: 413
+
+ GaugeFiller {
+ id: consumptionFiller
+ value: consumptionValue
+ anchors.fill: parent
+ numVertices: 64
+ radius: 233
+ fillWidth: 30
+ color: "#EF2973"
+ opacity: 0.3
+ minAngle: minValueAngle
+ maxAngle: maxValueAngle
+ minValue: minimumValue
+ maxValue: maximumValue
+ }
+
+ Item {
+ width: 465
+ height: 10
+ rotation: consumptionFiller.angle - 72
+ anchors.centerIn: parent
+
+ Image {
+ width: 144
+ height: 5
+ //opacity: 0.75
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+ }
+}
diff --git a/Cluster/qml/gauges/FpsMeter.qml b/Cluster/qml/gauges/FpsMeter.qml
new file mode 100644
index 0000000..b56739f
--- /dev/null
+++ b/Cluster/qml/gauges/FpsMeter.qml
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+import ".."
+
+Item {
+ id: fpsmeterNeedle
+
+ property real fpsmeterNeedleRotation: fpsValue * fpsDegreesPerValue
+ property real fpsValue: Math.min(fpscounter.fpsNow, 60) // Limit to 60, as that's where the gauge ends
+ property real maxValueAngle: 314
+ property real minValueAngle: 45
+ property real maximumValue: 60
+ property real fpsDegreesPerValue: Math.abs((maxValueAngle - minValueAngle) / maximumValue)
+
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.rightMargin: 887
+ anchors.topMargin: 125
+ width: 161
+ height: 10
+ rotation: fpsmeterNeedleRotation - 45
+
+ Image {
+ width: 56
+ height: 5
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+
+ FpsCounter {
+ id: fpscounter
+ rotation: fpsVisible ? -fpsmeterNeedle.rotation : 0
+ anchors.top: parent.top
+ anchors.topMargin: 50
+ anchors.horizontalCenter: parent.horizontalCenter
+ fpsVisible: false // Setting this to true prints fps on screen
+ running: startupAnimationsFinished
+ }
+ Behavior on fpsValue {
+ enabled: startupAnimationsFinished
+ PropertyAnimation { duration: fpscounter.fpsInterval }
+ }
+}
diff --git a/Cluster/qml/gauges/FuelMeter.qml b/Cluster/qml/gauges/FuelMeter.qml
new file mode 100644
index 0000000..3393e4f
--- /dev/null
+++ b/Cluster/qml/gauges/FuelMeter.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+
+Item {
+ property real fuelmeterNeedleRotation: fuelValue * fuelDegreesPerValue
+ property real fuelValue: ValueSource.fuelLevel
+ property real maxValueAngle: 170
+ property real minValueAngle: 10
+ property real maximumValue: 100
+ property real fuelDegreesPerValue: Math.abs((maxValueAngle - minValueAngle) / maximumValue)
+
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.rightMargin: 654
+ anchors.topMargin: 140
+ width: 158
+ height: 10
+ rotation: fuelmeterNeedleRotation - 80
+
+ Image {
+ width: 56
+ height: 5
+ //opacity: 0.75
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+}
diff --git a/Cluster/qml/gauges/SpeedoMeter.qml b/Cluster/qml/gauges/SpeedoMeter.qml
new file mode 100644
index 0000000..67d43de
--- /dev/null
+++ b/Cluster/qml/gauges/SpeedoMeter.qml
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+import com.qtcompany.clustergaugefiller 1.0
+
+Item {
+ anchors.fill: parent
+
+ property real speedometerNeedleRotation: 0.0
+ property string speed: actualSpeed.toFixed().toString()
+ property real actualSpeed: startupAnimationsFinished
+ ? ValueSource.kph : -speedometerNeedleRotation
+ property real maxValueAngle: 305
+ property real minValueAngle: 55
+ property real minimumSpeed: 0
+ property real maximumSpeed: 200
+
+ Item {
+ anchors.left: parent.left
+ anchors.leftMargin: 30
+ width: 720
+ height: 720
+
+ GaugeFiller {
+ id: speedFiller
+ value: actualSpeed
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.topMargin: 366
+ anchors.leftMargin: 382
+ radius: 232
+ fillWidth: 8
+ color: "#EF2973"
+ opacity: 0.6
+ maxAngle: maxValueAngle
+ minAngle: minValueAngle
+ minValue: minimumSpeed
+ maxValue: maximumSpeed
+ }
+ }
+
+ Item {
+ id: speedometerNeedle
+ width: 464
+ height: 10
+ rotation: speedFiller.angle - 35
+ x: 180
+ y: 361
+
+ Image {
+ opacity: 0.75
+ width: 146
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+ }
+
+ Row {
+ anchors.top: speedometerNeedle.bottom
+ anchors.topMargin: 120
+ anchors.horizontalCenter: speedometerNeedle.horizontalCenter
+ spacing: 10
+
+ Text {
+ font.pixelSize: 24
+ color:(ValueSource.gear === 0 && ValueSource.parkingBrake) ? "white" : "gray"
+ text: "P"
+ }
+
+ Text {
+ font.pixelSize: 24
+ //font.bold: ValueSource.gear === -1
+ color: ValueSource.gear === -1 ? "white" : "gray"
+ text: "R"
+ }
+
+ Text {
+ font.pixelSize: 24
+ //font.bold: ValueSource.gear === 0
+ color: (ValueSource.gear === 0 && !ValueSource.parkingBrake) ? "white" : "gray"
+ text: "N"
+ }
+
+ Text {
+ font.pixelSize: 24
+ //font.bold: ValueSource.gear === 1
+ color: ValueSource.gear === 1 ? "white" : "gray"
+ text: "D"
+ }
+ }
+
+ Text {
+ id: speedText
+ anchors.top: speedometerNeedle.top
+ anchors.topMargin: -40
+ anchors.horizontalCenter: speedometerNeedle.horizontalCenter
+ font.pixelSize: 60
+ color: "lightGray"
+ text: speed
+ }
+
+ Text {
+ id: speedUnitText
+ anchors.top: speedText.bottom
+ anchors.horizontalCenter: speedometerNeedle.horizontalCenter
+ font.pixelSize: 24
+ color: "lightGray"
+ text: "KM/H"
+ }
+}
diff --git a/Cluster/qml/gauges/TachoMeter.qml b/Cluster/qml/gauges/TachoMeter.qml
new file mode 100644
index 0000000..3fbd2c1
--- /dev/null
+++ b/Cluster/qml/gauges/TachoMeter.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+import com.qtcompany.clustergaugefiller 1.0
+
+Item {
+ anchors.fill: parent
+
+ property real tachometerNeedleRotation: 0.0
+ property string rpm: actualRPM.toFixed().toString()
+ property real actualRPM: startupAnimationsFinished
+ ? ValueSource.rpm : -tachometerNeedleRotation
+ property real minValueAngle: 55
+ property real maxValueAngle: 255
+ property real minimumRPM: 0
+ property real maximumRPM: 8000
+
+ Item {
+ anchors.right: parent.right
+ anchors.rightMargin: 30
+ width: 720
+ height: 720
+
+ GaugeFiller {
+ id: rpmFiller
+ value: actualRPM
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.topMargin: 369
+ anchors.rightMargin: 380
+ radius: 232
+ fillWidth: 8
+ color: "#EF2973"
+ opacity: 0.6
+ minAngle: minValueAngle
+ maxAngle: maxValueAngle
+ minValue: minimumRPM
+ maxValue: maximumRPM
+ }
+ }
+
+ Item {
+ id: tachometerNeedle
+ width: 468
+ height: 10
+ rotation: rpmFiller.angle - 35
+ x: 1275
+ y: 363
+
+ Image {
+ opacity: 0.75
+ width: 147
+ anchors.left: parent.left
+ anchors.leftMargin: 2
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+ }
+
+ Text {
+ id: textEco
+ anchors.top: tachometerNeedle.top
+ anchors.topMargin: -10
+ anchors.horizontalCenter: tachometerNeedle.horizontalCenter
+ text: actualRPM > 4000 ? "POWER" : "ECO"
+ font.pixelSize: 24
+ color: actualRPM <= 4000 ? "white" : "red"
+ }
+}
diff --git a/Cluster/qml/gauges/TemperatureMeter.qml b/Cluster/qml/gauges/TemperatureMeter.qml
new file mode 100644
index 0000000..67c2a8a
--- /dev/null
+++ b/Cluster/qml/gauges/TemperatureMeter.qml
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+import com.qtcompany.clustergaugefiller 1.0
+
+Item {
+ property real temperatureValue: ValueSource.engineTemperature
+ property real minValueAngle: 42.5
+ property real maxValueAngle: -42.5
+ property real minimumValue: 40
+ property real maximumValue: 120
+
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.rightMargin: 965
+ anchors.topMargin: 90
+
+ GaugeFiller {
+ id: temperatureFiller
+ value: temperatureValue
+ anchors.fill: parent
+ numVertices: 64
+ radius: 210
+ fillWidth: 38
+ color: "#EF2973"
+ opacity: 0.3
+ minAngle: minValueAngle
+ maxAngle: maxValueAngle
+ minValue: minimumValue
+ maxValue: maximumValue
+ }
+
+ Item {
+ width: 420
+ height: 10
+ rotation: temperatureFiller.angle - 47.5
+ anchors.centerIn: parent
+
+ Image {
+ width: 38
+ height: 5
+ //opacity: 0.75
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+ }
+}
diff --git a/Cluster/qml/gauges/TurboMeter.qml b/Cluster/qml/gauges/TurboMeter.qml
new file mode 100644
index 0000000..c1a37cc
--- /dev/null
+++ b/Cluster/qml/gauges/TurboMeter.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import service.valuesource 1.0
+
+Item {
+ property real turbometerNeedleRotation: turboValue * turboDegreesPerValue
+ property real turboValue: ValueSource.rpm / 2000.
+ property real maxValueAngle: 270
+ property real minValueAngle: 0
+ property real maximumValue: 4.0
+ property real turboDegreesPerValue: Math.abs((maxValueAngle - minValueAngle) / maximumValue)
+
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.leftMargin: 639
+ anchors.topMargin: 140
+ width: 164
+ height: 10
+ rotation: turbometerNeedleRotation - 90
+
+ Image {
+ width: 57
+ height: 5
+ //opacity: 0.75
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ source: "../../images/SpeedometerNeedle.png"
+ }
+}
diff --git a/Cluster/qml/models/Map11.jpg b/Cluster/qml/models/Map11.jpg
new file mode 100644
index 0000000..5b81424
--- /dev/null
+++ b/Cluster/qml/models/Map11.jpg
Binary files differ
diff --git a/Cluster/qml/models/sportscar.qgltf b/Cluster/qml/models/sportscar.qgltf
new file mode 100644
index 0000000..7b30a0d
--- /dev/null
+++ b/Cluster/qml/models/sportscar.qgltf
Binary files differ
diff --git a/Cluster/qml/models/sportscar_1.bin b/Cluster/qml/models/sportscar_1.bin
new file mode 100644
index 0000000..bf5f16d
--- /dev/null
+++ b/Cluster/qml/models/sportscar_1.bin
Binary files differ
diff --git a/Cluster/qtcluster.qrc b/Cluster/qtcluster.qrc
new file mode 100644
index 0000000..cc1c63b
--- /dev/null
+++ b/Cluster/qtcluster.qrc
@@ -0,0 +1,13 @@
+<RCC>
+ <qresource prefix="/">
+ <file>../demo-assets/fonts/Lato-Bold.ttf</file>
+ <file>../demo-assets/fonts/Lato-Regular.ttf</file>
+ <file>../demo-assets/fonts/Lato-Semibold.ttf</file>
+ <file>qml/FpsCounter.qml</file>
+ <file>qml/Dashboard.qml</file>
+ <file>qml/DashboardFrame.qml</file>
+ <file>qml/DashboardView.qml</file>
+ <file>qml/CarModel.qml</file>
+ <file>qml/WelcomeView.qml</file>
+ </qresource>
+</RCC>
diff --git a/Cluster/sportscar.qrc b/Cluster/sportscar.qrc
new file mode 100644
index 0000000..feb6358
--- /dev/null
+++ b/Cluster/sportscar.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="Map11.jpg">qml/models/Map11.jpg</file>
+ <file alias="sportscar.qgltf">qml/models/sportscar.qgltf</file>
+ <file alias="sportscar_1.bin">qml/models/sportscar_1.bin</file>
+ </qresource>
+</RCC>
diff --git a/Cluster/sportscar_15k.qrc b/Cluster/sportscar_15k.qrc
new file mode 100644
index 0000000..c0a1df9
--- /dev/null
+++ b/Cluster/sportscar_15k.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="Map11.jpg">qml/models/Map11.jpg</file>
+ <file alias="sportscar.qgltf">qml/models/sportscar_15k.qgltf</file>
+ <file alias="sportscar_15k_1.bin">qml/models/sportscar_15k_1.bin</file>
+ </qresource>
+</RCC>
diff --git a/Cluster/sportsimages.qrc b/Cluster/sportsimages.qrc
new file mode 100644
index 0000000..641ae9b
--- /dev/null
+++ b/Cluster/sportsimages.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/MapLocationSport.png</file>
+ </qresource>
+</RCC>
diff --git a/Cluster/sportsqml.qrc b/Cluster/sportsqml.qrc
new file mode 100644
index 0000000..020b33a
--- /dev/null
+++ b/Cluster/sportsqml.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/Dashboard.qml</file>
+ <file>qml/DashboardFrame.qml</file>
+ <file>qml/CarModel.qml</file>
+ <file>qml/DashboardView.qml</file>
+ </qresource>
+</RCC>
diff --git a/LICENSE.GPL3-EXCEPT b/LICENSE.GPL3-EXCEPT
new file mode 100644
index 0000000..b1cb1be
--- /dev/null
+++ b/LICENSE.GPL3-EXCEPT
@@ -0,0 +1,704 @@
+This is the GNU General Public License version 3, annotated with The
+Qt Company GPL Exception 1.0:
+
+-------------------------------------------------------------------------
+
+The Qt Company GPL Exception 1.0
+
+Exception 1:
+
+As a special exception you may create a larger work which contains the
+output of this application and distribute that work under terms of your
+choice, so long as the work is not otherwise derived from or based on
+this application and so long as the work does not in itself generate
+output that contains the output from this application in its original
+or modified form.
+
+Exception 2:
+
+As a special exception, you have permission to combine this application
+with Plugins licensed under the terms of your choice, to produce an
+executable, and to copy and distribute the resulting executable under
+the terms of your choice. However, the executable must be accompanied
+by a prominent notice offering all users of the executable the entire
+source code to this application, excluding the source code of the
+independent modules, but including any changes you have made to this
+application, under the terms of this license.
+
+
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Main.qml b/Main.qml
new file mode 100644
index 0000000..2ea5867
--- /dev/null
+++ b/Main.qml
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+import QtQuick 2.1
+import QtQuick.Window 2.1
+import QtApplicationManager 1.0
+import com.pelagicore.ScreenManager 1.0
+import utils 1.0
+import "Cluster/qml"
+import "CenterConsole"
+import "CenterConsole/sysui/StatusBar"
+import "CenterConsole/sysui/BottomBar"
+import "CenterConsole/sysui"
+
+Rectangle {
+ id: root
+
+ property var cluster
+ property bool showClusterIfPossible: ApplicationManager.additionalConfiguration.showCluster
+
+ Item {
+ id: centerConsole
+ width: Style.screenWidth
+ height: Style.screenHeight
+ rotation: -90
+ y: -420
+ x: 420
+
+ Component {
+ id: topMenu
+ CenterScreen {
+ }
+ }
+
+ StatusBar {
+ id: statusBar
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+
+ LaunchController {
+ id: launcher
+ anchors.top: statusBar.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: centerConsole.height - statusBar.height - Style.bottomBarHeight
+ width: parent.width
+ initialItem: topMenu
+ }
+ BottomBar {
+ id: climateBar
+ anchors.bottom: parent.bottom
+ }
+ }
+
+ Component{
+ id: clusterComponent
+ Window {
+ id: cluster
+ title: "Cluster Display"
+ height: 720
+ width: 1920
+ visible: false
+
+ color: "black"
+
+ DashboardFrame {}
+
+ Component.onCompleted: {
+ WindowManager.registerCompositorView(cluster)
+ ScreenManager.setScreen(cluster, 1)
+ cluster.show()
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ var canDisplayCluster = WindowManager.runningOnDesktop || ScreenManager.screenCount() > 1
+
+ if (!showClusterIfPossible) {
+ console.log("Showing Instrument Cluster was disabled");
+ return
+ }
+
+ if (canDisplayCluster) {
+ console.log("Showing Instrument Cluster");
+ cluster = clusterComponent.createObject(root);
+ } else {
+ console.log("Showing the Instrument Cluster is not possible on this platform");
+ }
+ }
+
+}
diff --git a/MainWithClusterAndPassenger.qml b/MainWithClusterAndPassenger.qml
new file mode 100644
index 0000000..4cd5733
--- /dev/null
+++ b/MainWithClusterAndPassenger.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Window 2.1
+import QtApplicationManager 1.0
+import com.pelagicore.ScreenManager 1.0
+import utils 1.0
+import "Cluster/qml"
+import "CenterConsole"
+import "PassengerView"
+
+Main {
+ id: root
+
+ Window {
+ id: cluster
+ title: "Cluster Display"
+ height: 720
+ width: 1920
+ visible: false
+
+ color: "black"
+
+ DashboardFrame {}
+
+ Component.onCompleted: {
+ WindowManager.registerCompositorView(cluster)
+ Style.withCluster = true
+ ScreenManager.setScreen(cluster, 1)
+ cluster.show()
+ }
+ }
+ Window {
+ id: passengerView
+ title: "Passenger Display"
+ width: Style.screenHeight
+ height: Style.screenWidth
+ visible: false
+
+ color: "black"
+
+ PassengerView {}
+
+ Component.onCompleted: {
+ WindowManager.registerCompositorView(passengerView)
+ Style.withPassengerView = true
+ ScreenManager.setScreen(passengerView, 2)
+ passengerView.show()
+ }
+ }
+
+
+ Window.onActiveChanged: {
+ if (Window.active && !WindowManager.runningOnDesktop)
+ cluster.requestActivate()
+ }
+}
diff --git a/PassengerView/PassengerView.qml b/PassengerView/PassengerView.qml
new file mode 100644
index 0000000..7e03752
--- /dev/null
+++ b/PassengerView/PassengerView.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import models 1.0
+import utils 1.0
+
+Item {
+ width: Style.screenHeight
+ height: Style.screenWidth
+
+ Item {
+ id: musicContainer
+ anchors.fill: parent
+ default property alias content: musiccontainer.children
+
+ Item {
+ id: musiccontainer
+ anchors.fill: parent
+ }
+ }
+ Connections {
+ target: ApplicationManagerInterface
+ onPassengerWidgetReady: {
+ handleWidgetChange(category, item)
+ }
+ }
+ function handleWidgetChange(category, item) {
+ var container
+ if (category === "media") {
+ container = musicContainer
+ container.visible = true
+ item.parent = container
+ container.content = item
+ item.width = container.width
+ item.height = container.height
+ }
+ }
+}
diff --git a/README b/README
new file mode 100644
index 0000000..7ce948a
--- /dev/null
+++ b/README
@@ -0,0 +1,74 @@
+# Overview
+ * The Multiscreen Demo is based on the Neptune UI code which is provided as a part of the Qt Automotive Suite (https://doc.qt.io/QtAutomotiveSuite/).
+ In its implementation, the Multiscreen Demo provides an alternative implementation for a few selected use cases in automotive UIs, e.g.,
+ the use of 3D content, integration of the CAN-bus interfaces or a use of multiple screens. Please be aware that in the future this
+ repository's functionality might get merged into the Neptune UI and this repository would be deleted.
+
+ * Multiscreen Demo implements the ability to use simulated events to 'drive' along a hardcoded route and also ability to control
+ events sent to cluster through CanController. By default, demo runs in fully automatic mode and events are simulated.
+ If you want to control the events, you can use CanController. The CanController synthesizes events and can deliver them via CAN or TCP.
+ TCP is strongly recommended (unless you know better) as the CAN interface can produce 8-bit overflow issues and other unnoted problems,
+ which should be investigated later. If you have want to use the CanController, it can be activated by setting the "fullDemo" property
+ to false in ValueSource.qml:
+
+ //
+ // ENABLE FOR FULLY AUTOMATIC DEMO MODE (in case there is no CanController)
+ //
+ property bool fullDemo: true//false
+
+ You can find the ValueSource.qml file under /opt/automotivedemo/imports/shared/service/valuesource
+ in HW, or automotivedemo\imports\shared\service\valuesource in project hierarchy.
+
+ The CanController (client) synthesizes CAN events, while the automotivedemo (server) responds to said events.
+
+ If you really want to use CAN, you will probably want to use the SocketCAN driver, which can be set up on a Linux system using the following
+ commands:
+
+ sudo modprobe vcan
+ sudo ip link add dev can0 type vcan
+ sudo ip link set up can0
+
+ * At least Qt 5.8 is required to build automotivedemo. Currently only TCP is supported in this automotivedemo.
+
+# Walkthrough
+
+ * OPTIONAL: Chose your data sources (using TCP, or create your CAN devices as necessary).
+
+ * Build plugins from automotivedemo repository
+
+ qmake -r INSTALL_PREFIX=/opt
+ make & make install
+
+ * Run apps
+
+ OPTIONAL:
+ If TCP connection is used, get the IP address from the device where automotivedemo is installed.
+ Then use the IP address in CanController on runtime by defining QT_CLUSTER_SIMU env variable
+ e.g. QT_CLUSTER_SIMU=192.168.0.1 by default it is localhost 127.0.0.1.
+
+ In device set the following environment variable. If there are two screens available, application will
+ automatically show both cluster center console views:
+ export QT_QPA_EGLFS_KMS_CONFIG=<deployed kms_config.json file from automotivedemo git>
+
+ Run in desktop
+ appman.exe -r -c \qtapplicationmanager\template-opt\am\config.yaml -c am-config.yaml --dbus none Main.qml
+
+ In device:
+ chmod +x /opt/automotivedemo/start.sh
+ ./start.sh
+
+# Making it run automatically in HW
+
+ Disable neptune-ui and enable automotive demo to startup during device boot:
+ adb shell
+ systemctl disable neptune
+ systemctl enable automotivedemo
+ systemctl start automotivedemo
+
+Typical errors:
+ * If you are not seeing the route in the map after you have selected destination, make sure that openssl libraries are found. Route feature is available
+ only from Qt5.8 onwards.
+ * "QtQuick.VirtualKeyboard is not installed" -> set environmentvariable QT_IM_MODULE=qtvirtualkeyboard
+ * In Qt5.8.0 maps are not working offline, bug in https://bugreports.qt.io/browse/QTBUG-57011
+ In case offline maps are needed, checkout following commit from qtlocation and recompile mapbox plugin:
+ https://codereview.qt-project.org/#/c/176591/
diff --git a/am-config.yaml b/am-config.yaml
new file mode 100644
index 0000000..d0e40e8
--- /dev/null
+++ b/am-config.yaml
@@ -0,0 +1,32 @@
+formatVersion: 1
+formatType: am-configuration
+---
+# basic AM functionality - the builtin apps are in 'apps'.
+
+applications:
+ builtinAppsManifestDir: "CenterConsole/apps"
+
+# QML apps will be able to import from modules...
+
+runtimes:
+ qml:
+ importPaths: [ "imports/shared", "qml" ]
+
+# ... as well as the SystemUI
+
+ui:
+ fullscreen: yes
+ mainQml: "Main.qml"
+ importPaths: [ "imports/shared", "imports/system", "qml" ]
+ additionalConfiguration:
+ appStoreServerUrl: 'http://chaos.pelagicore.net:8080'
+ styleConfig: "auto"
+ showCluster: yes
+ windowIcon: "imports/shared/assets/icons/active/apps@96.png"
+
+# development setup: no security
+
+flags:
+ noSecurity: yes
+ noUiWatchdog: yes
+
diff --git a/automotivedemo.pro b/automotivedemo.pro
new file mode 100644
index 0000000..35f74b8
--- /dev/null
+++ b/automotivedemo.pro
@@ -0,0 +1,17 @@
+include (deployment.pri)
+TEMPLATE = subdirs
+
+SUBDIRS = \
+ CenterConsole \
+ Cluster
+
+qml.files = imports kms_config.json Main.qml am-config.yaml start.sh
+qml.path = $$TARGET_PATH
+
+fonts.files = demo-assets/fonts/Lato-Bold.ttf \
+ demo-assets/fonts/Lato-Light.ttf \
+ demo-assets/fonts/Lato-Regular.ttf \
+ demo-assets/fonts/Lato-Semibold.ttf
+fonts.path = $$TARGET_PATH/imports/shared/assets/fonts
+
+INSTALLS += qml fonts
diff --git a/defaults.pri b/defaults.pri
new file mode 100644
index 0000000..20872d4
--- /dev/null
+++ b/defaults.pri
@@ -0,0 +1,6 @@
+
+
+### Included through .qmake.conf, for global build config stuff
+
+isEmpty(INSTALL_PREFIX):PREFIX=/usr/local
+
diff --git a/demo-assets b/demo-assets
new file mode 160000
+Subproject 0d47d21f082d6c9e355a55809ebd38a31ea0226
diff --git a/deployment.pri b/deployment.pri
new file mode 100644
index 0000000..9351b4d
--- /dev/null
+++ b/deployment.pri
@@ -0,0 +1,3 @@
+TARGET_PATH = $$INSTALL_PREFIX/automotivedemo
+TARGET_PATH_CLUSTER = $$INSTALL_PREFIX/automotivedemo/Cluster
+TARGET_PATH_CONSOLE = $$INSTALL_PREFIX/automotivedemo/CenterConsole
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/backspace-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/backspace-868482.svg
new file mode 100644
index 0000000..09928cc
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/backspace-868482.svg
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ viewBox="-420 107 159 88"
+ enable-background="new -420 107 159 88"
+ xml:space="preserve"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="backspace-868482.svg"><metadata
+ id="metadata3483"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs3481" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1136"
+ id="namedview3479"
+ showgrid="false"
+ inkscape:zoom="4.327044"
+ inkscape:cx="109.27575"
+ inkscape:cy="20.181193"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g3463" /><g
+ id="g3459"><rect
+ x="-420"
+ y="107"
+ fill="none"
+ width="159"
+ height="88"
+ id="rect3461" /><g
+ id="g3463"><g
+ id="g3465"><path
+ d="m -261.2,195 -114.8,0 -44,-44 44,-44 114.8,0 z m -112.17994,-3.67355 107.81308,-0.2311 0,-79.72849 -108.27529,0 -39.40204,39.40204 z"
+ id="path3467"
+ inkscape:connector-curvature="0"
+ style="fill:#868482"
+ sodipodi:nodetypes="cccccccccccc" /></g><g
+ id="g3469"
+ transform="translate(5.315407,3.0043605)"><g
+ id="g3471"><rect
+ x="-327.47067"
+ y="128.42934"
+ transform="matrix(-0.7071,-0.7071,0.7071,-0.7071,-665.0558,26.5252)"
+ width="6.0706396"
+ height="50.470654"
+ id="rect3473"
+ style="fill:#868482" /></g><g
+ id="g3475"><rect
+ x="-351.79507"
+ y="151.44643"
+ transform="matrix(-0.7071,-0.7071,0.7071,-0.7071,-665.0499,26.5255)"
+ width="52.595058"
+ height="5.2535815"
+ id="rect3477"
+ style="fill:#868482" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/check-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/check-868482.svg
new file mode 100644
index 0000000..c8af5f3
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/check-868482.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="-414 91 170 119" enable-background="new -414 91 170 119" xml:space="preserve">
+<g>
+ <polygon fill="#868482" points="-351.7,210 -414,147.7 -402.7,136.3 -351.7,187.3 -255.3,91 -244,102.3 "/>
+</g>
+</svg>
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/enter-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/enter-868482.svg
new file mode 100644
index 0000000..75080f6
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/enter-868482.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="-394 111 211 80" enable-background="new -394 111 211 80" xml:space="preserve">
+<g>
+ <rect x="-394" y="111" fill="none" width="211" height="80"/>
+ <g>
+ <rect x="-384.8" y="144.8" fill="#868482" width="201.8" height="12.3"/>
+ <rect x="-195.3" y="121.7" fill="#868482" width="12.3" height="35.3"/>
+ <polygon fill="#868482" points="-349.5,111 -349.5,190.8 -394,151.7 "/>
+ </g>
+</g>
+</svg>
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/globe-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/globe-868482.svg
new file mode 100644
index 0000000..318fea8
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/globe-868482.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ viewBox="-427 79 144 144"
+ enable-background="new -427 79 144 144"
+ xml:space="preserve"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="globe-868482.svg"><metadata
+ id="metadata3793"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs3791" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1136"
+ id="namedview3789"
+ showgrid="false"
+ inkscape:zoom="4.6354778"
+ inkscape:cx="15.443116"
+ inkscape:cy="49.492945"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1" /><g
+ id="g3781"><rect
+ x="-427"
+ y="79"
+ fill="none"
+ width="144"
+ height="144"
+ id="rect3783" /><g
+ id="g3785"><path
+ d="m -355,223 c -39.5,0 -71.8,-32.1 -72,-71.6 -0.2,-39.7 31.9,-72.2 71.6,-72.4 l 0.7,0 c 19.1,0.1 37.1,7.6 50.6,21.1 13.5,13.5 21,31.5 21.1,50.5 0.1,19.2 -7.3,37.4 -20.8,51 -13.5,13.7 -31.6,21.3 -50.8,21.4 z m 3.22136,-42.7 0,35.96737 c 9,-8.1 18.80446,-20.05728 23.40446,-30.85728 -6.7,-2 -16.40446,-4.71009 -23.40446,-5.11009 z M -380,183.9 c 3.2,7.4 9.01009,18.18309 14.31009,24.48309 2.4,2.9 5.74718,4.95282 8.54718,7.45282 L -357.57418,180.3 c -7,0.4 -15.62582,1.6 -22.42582,3.6 z m 58.2,3 c -3.9,9.1 -15.88755,21.48309 -22.58755,28.98309 10.4,-2.9 26.58755,-12.38309 34.48755,-20.28309 0.5,-0.5 1,-1.1 1.6,-1.6 -4.4,-2.9 -8.9,-5.2 -13.5,-7.1 z m -82.073,8.72582 c 7.8,8.5 28.47064,18.03591 39.87064,21.23591 -0.5,-0.6 -4.98309,-5.51455 -5.48309,-6.11455 -6,-7.1 -11.01573,-15.54718 -14.51573,-23.94718 -4.7,2 -15.57182,6.02582 -19.87182,8.82582 z m 83.03145,-13.68991 c 5.5,2.3 12.95728,7.04155 18.05728,10.34155 6.5,-9.4 12.773,-28.06619 13.573,-39.56619 l -25.48873,0 c -0.1,1.2 -0.1,4.98873 -0.2,6.28873 -0.7,6.8 -3.94155,16.63591 -5.94155,22.93591 z m -100.59436,-27.93027 c 0.8,11.8 7.60446,27.13027 14.00446,36.33027 5.1,-3.3 15.36173,-6.96291 20.76173,-9.26291 -2.4,-7.5 -8.23028,-19.71455 -8.63028,-27.71455 z m 31.16854,-0.64719 c 0.3,7 6.03028,19.84037 8.13028,26.44037 7.7,-2.4 16.56291,-3.36854 24.56291,-3.66854 l 0.21573,-23.20328 z m 38.48873,22.34037 c 8,0.4 16.97864,2.77864 24.67864,5.17864 1.7,-5.6 5.70446,-15.59882 6.20446,-21.59882 0.1,-1 0.53145,-6.53028 0.63145,-7.43028 l -31.51455,0.64718 z M -314.8,146.7 l 25.58873,0 c -0.8,-11.5 -6.973,-24.55727 -13.573,-33.95727 -5.1,3.4 -11.79437,5.76854 -17.39437,8.06854 2.5,7.5 4.97864,17.88873 5.37864,25.88873 z m -37.19436,0.86291 31.73027,-1.07864 c -0.4,-7 -3.32582,-17.46736 -5.42582,-24.06736 -7.7,2.4 -18.95164,4.34718 -26.95164,4.74718 z m -37.95728,0.43145 32.16173,0 0,-20.83027 c -7.9,-0.4 -20.97746,-0.83709 -28.57746,-3.23709 -1.8,5.8 -3.21572,13.41009 -3.81572,19.61009 -0.1,0.8 0.23145,3.65727 0.23145,4.45727 z m -31.69999,0.86292 26.45163,-0.64719 c 0.1,-1 0.1,-3.51009 0.2,-4.51009 0.6,-7 2,-13.8 4,-20.3 -5.5,-2.3 -13.92018,-6.39436 -19.02018,-9.79436 -6.4,9.1 -10.83145,23.45164 -11.63145,35.25164 z m 68.57863,-63.07183 0.21573,35.69882 c 6.9,-0.3 18.23027,-1.5 24.93027,-3.5 -1.37418,-7.31572 -7.3,-14.54718 -12.5,-20.64718 -2.4,-2.9 -9.846,-9.05164 -12.646,-11.55164 z m -30.94155,33.27746 c 6.7,2 18.89319,2.33709 25.79319,2.63709 l 0.64718,-35.698822 c -8.9,7.9 -21.84037,22.461732 -26.44037,33.061732 z m 38.29554,-34.224642 c 0.8,0.9 7.42465,6.977459 8.22465,7.977459 5.9,6.9 11.89436,14.384273 15.39436,22.484273 4.7,-2 12.96737,-4.73145 17.36737,-7.63145 -0.6,-0.6 -1.63146,-1.84719 -2.23146,-2.54719 -9.29436,-11.451637 -28.15492,-17.483092 -38.75492,-20.283092 z M -406.246,107.88427 c 4.4,2.8 12.78309,7.78873 17.48309,9.68873 4,-9.3 17.48192,-24.803277 24.48192,-32.303277 -11.8,3.2 -33.96501,13.91455 -41.96501,22.614547 z"
+ id="path3787"
+ inkscape:connector-curvature="0"
+ style="fill:#868482"
+ sodipodi:nodetypes="scccscccscccccccccccscccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" /></g></g></svg> \ No newline at end of file
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/handwriting-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/handwriting-868482.svg
new file mode 100644
index 0000000..1474654
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/handwriting-868482.svg
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ viewBox="0 0 156 104"
+ enable-background="new 0 0 156 104"
+ xml:space="preserve"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="handwriting-868482.svg"><metadata
+ id="metadata3399"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs3397" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1136"
+ id="namedview3395"
+ showgrid="false"
+ inkscape:zoom="9.2948718"
+ inkscape:cx="83.191118"
+ inkscape:cy="52"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1" /><g
+ id="g3387"><g
+ id="g3389"><path
+ d="m 37.922759,97.167586 c -10.1,0 -11.046207,-1.342069 -16.967587,-8.651034 -8.271034,-21 1.526897,-31.697931 17.826897,-48.997931 1.2,-1.2 7.241379,-9.493104 8.441379,-10.793104 5.3,-5.7 1.111724,-14.727586 -0.588276,-18.027586 -1.8,-3.4 -11.309655,-4.0393103 -16.009655,-3.3393103 -16.5,2.6 -24.7503446,30.7034483 -24.7503446,30.9034483 L 0,36.6 C 0.3,35.3 6.4,4.3 31.2,0.3 41,-1.3 49.7,2.7 53.9,10.7 c 4.7,8.9 2.6,20.1 -5.3,28.6 -1.2,1.3 -2.4,2.6 -3.6,3.8 -16.7,17.8 -25.9,28.5 -19.6,41.4 3.3,6.8 11.1,7.6 16.9,6.3 C 51.5,88.7 62.1,79.7 62,61.3 61.8,33.2 78.2,19.5 92.2,16.4 c 14.5,-3.2 26.67862,3.922759 32.97862,17.322759 1.3,2.8 2.83793,5.077241 3.63793,7.777241 13.3,0.7 25.82276,5.375862 26.32276,5.475862 l -2.32414,5.044828 c -0.1,0 -12.71241,-4.306207 -23.61241,-5.306207 2.11379,17.360689 -3.65104,36.323448 -15.68897,41.155172 C 101.61379,93.869655 87.9,92.1 83,83.1 79.9,77.5 81.1,68.4 85.9,60.6 c 7.9,-13 25.71103,-17.615172 35.91103,-19.015172 -0.4,-1.2 -3.26689,-7.456552 -3.76689,-8.456552 -3.9,-8.3 -16.07311,-13.368276 -24.973106,-11.368276 -9.7,2.2 -26.056551,18.017241 -25.856551,39.017241 0.2,25.5 -9.682759,32.613104 -23.082759,35.813104 -2.6,0.6 -3.808965,0.577241 -6.208965,0.577241 z M 123.02759,47.137241 c -14,1.5 -27.377935,6.671035 -32.222073,16.235173 -4.569547,5.48009 -6.825089,15.074863 -1.501379,19.937241 10.744832,7.956552 19.564832,1.708966 24.404142,-1.198621 10.58482,-6.253103 9.81931,-26.073793 9.31931,-34.973793 z"
+ id="path3391"
+ inkscape:connector-curvature="0"
+ style="fill:#868482"
+ sodipodi:nodetypes="sccccccccccccccccccccccccccccsccccc" /></g><rect
+ fill="none"
+ width="156"
+ height="104"
+ id="rect3393" /></g></svg> \ No newline at end of file
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/hidekeyboard-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/hidekeyboard-868482.svg
new file mode 100644
index 0000000..5443e30
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/hidekeyboard-868482.svg
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ viewBox="-427 87 144 127"
+ enable-background="new -427 87 144 127"
+ xml:space="preserve"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="hidekeyboard-868482.svg"><metadata
+ id="metadata3534"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs3532" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1136"
+ id="namedview3530"
+ showgrid="false"
+ inkscape:zoom="3.8188977"
+ inkscape:cx="57.633466"
+ inkscape:cy="81.826203"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g3468" /><g
+ id="g3464"><rect
+ x="-427"
+ y="87"
+ fill="none"
+ width="144"
+ height="127"
+ id="rect3466" /><g
+ id="g3468"><g
+ id="g3470" /><g
+ id="g3498"
+ transform="matrix(0.6642876,0,0,0.60833553,-135.10074,52.111516)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500"
+ style="fill:#868482" /></g><g
+ id="g3522"
+ transform="matrix(1,0,0,0.53000264,-0.26185567,72.641448)"><rect
+ x="-388.89999"
+ y="146.2"
+ width="67.699997"
+ height="11.7"
+ id="rect3524"
+ style="fill:#868482" /></g><polygon
+ style="fill:#868482"
+ id="polygon3528"
+ points="-381.1,195.2 -355,213.9 -328.9,195.2 -345.2,195.2 -355,202.2 -364.8,195.2 " /><g
+ id="g3498-5"
+ transform="matrix(0.6642876,0,0,0.60833553,-116.19714,52.058942)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7"
+ style="fill:#868482" /></g><g
+ id="g3498-5-4"
+ transform="matrix(0.6642876,0,0,0.60833553,-78.8827,51.666158)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-0"
+ style="fill:#868482" /></g><g
+ id="g3498-5-43"
+ transform="matrix(0.6642876,0,0,0.60833553,-97.474452,51.928014)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-4"
+ style="fill:#868482" /></g><g
+ id="g3498-5-2"
+ transform="matrix(0.6642876,0,0,0.60833553,-60.16002,51.666158)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-6"
+ style="fill:#868482" /></g><g
+ id="g3498-5-3"
+ transform="matrix(0.6642876,0,0,0.60833553,-41.568267,51.797086)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-64"
+ style="fill:#868482" /></g><g
+ id="g3498-5-0"
+ transform="matrix(0.6642876,0,0,0.60833553,-41.306411,32.419767)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-60"
+ style="fill:#868482" /></g><g
+ id="g3498-5-5"
+ transform="matrix(0.6642876,0,0,0.60833553,-60.290947,32.419767)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-1"
+ style="fill:#868482" /></g><g
+ id="g3498-5-34"
+ transform="matrix(0.6642876,0,0,0.60833553,-78.751772,32.288839)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-8"
+ style="fill:#868482" /></g><g
+ id="g3498-5-28"
+ transform="matrix(0.6642876,0,0,0.60833553,-97.60538,32.419766)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-08"
+ style="fill:#868482" /></g><g
+ id="g3498-5-8"
+ transform="matrix(0.6642876,0,0,0.60833553,-116.45899,32.288839)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-66"
+ style="fill:#868482" /></g><g
+ id="g3498-5-6"
+ transform="matrix(0.6642876,0,0,0.60833553,-134.91981,32.550694)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-7-85"
+ style="fill:#868482" /></g><g
+ id="g3498-2"
+ transform="matrix(0.56357388,0,0,7.7030576,-197.43282,-888.87016)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-3"
+ style="fill:#868482" /></g><g
+ id="g3498-2-4"
+ transform="matrix(0.56357388,0,0,7.7030576,-59.762201,-888.87016)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-3-6"
+ style="fill:#868482" /></g><g
+ id="g3498-50"
+ transform="matrix(11.474227,0,0,0.60833553,4253.5026,93.039354)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-1"
+ style="fill:#868482" /></g><g
+ id="g3498-50-9"
+ transform="matrix(11.474227,0,0,0.60833553,4252.9789,9.9001791)"><rect
+ x="-407.5"
+ y="126.7"
+ width="11.7"
+ height="11.7"
+ id="rect3500-1-4"
+ style="fill:#868482" /></g><path
+ style="fill:#999999;fill-opacity:1"
+ d="m -0.0757732,45.191067 0,-45.0182098 3.2404639,-0.08614494 C 7.3998563,-0.02587596 134.35087,-0.02575465 139.85335,0.08684287 l 4.22242,0.08640373 0,45.0180154 0,45.018016 -72.07577,0 -72.0757732,0 0,-45.018211 z m 137.7360832,-0.08643 0,-38.0345359 -65.594846,0 -65.5948454,0 0,38.0345359 0,38.034536 65.5948454,0 65.594846,0 0,-38.034536 z"
+ id="path3720"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#ffffff"
+ d="m 21.265464,45.759278 0,-3.469587 3.796907,0 3.796907,0 0,3.469587 0,3.469588 -3.796907,0 -3.796907,0 0,-3.469588 z"
+ id="path3722"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 21.396392,26.185567 0,-3.535052 3.862371,0 3.862371,0 0,3.535052 0,3.535052 -3.862371,0 -3.862371,0 0,-3.535052 z"
+ id="path3724"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 39.857216,25.923711 0,-3.535051 3.862372,0 3.862371,0 0,3.535051 0,3.535052 -3.862371,0 -3.862372,0 0,-3.535052 z"
+ id="path3726"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#ffffff"
+ d="m 40.119072,45.693814 0,-3.535051 3.862371,0 3.862371,0 0,3.535051 0,3.535052 -3.862371,0 -3.862371,0 0,-3.535052 z"
+ id="path3728"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 58.841753,45.562887 0,-3.535052 3.862371,0 3.862371,0 0,3.535052 0,3.535051 -3.862371,0 -3.862371,0 0,-3.535051 z"
+ id="path3730"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#ffffff"
+ d="m 58.710825,26.054639 0,-3.535051 3.862371,0 3.862371,0 0,3.535051 0,3.535052 -3.862371,0 -3.862371,0 0,-3.535052 z"
+ id="path3732"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 77.564433,25.923711 0,-3.535051 3.862371,0 3.862371,0 0,3.535051 0,3.535052 -3.862371,0 -3.862371,0 0,-3.535052 z"
+ id="path3734"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 77.433505,45.301031 0,-3.535052 3.862371,0 3.862371,0 0,3.535052 0,3.535051 -3.862371,0 -3.862371,0 0,-3.535051 z"
+ id="path3736"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 96.156186,45.301031 0,-3.535052 3.862374,0 3.86237,0 0,3.535052 0,3.535051 -3.86237,0 -3.862374,0 0,-3.535051 z"
+ id="path3738"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 96.025258,26.054639 0,-3.535051 3.862371,0 3.862371,0 0,3.535051 0,3.535052 -3.862371,0 -3.862371,0 0,-3.535052 z"
+ id="path3740"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 115.00979,26.054639 0,-3.535051 3.86237,0 3.86238,0 0,3.535051 0,3.535052 -3.86238,0 -3.86237,0 0,-3.535052 z"
+ id="path3742"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 114.74794,45.431959 0,-3.535052 3.86237,0 3.86237,0 0,3.535052 0,3.535051 -3.86237,0 -3.86237,0 0,-3.535051 z"
+ id="path3744"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 37.893299,66.249485 0,-3.011341 33.779381,0 33.77938,0 0,3.011341 0,3.01134 -33.77938,0 -33.779381,0 0,-3.01134 z"
+ id="path3746"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 64.14433,121.20799 c -4.320619,-3.09875 -10.146368,-7.27582 -12.94611,-9.28238 l -5.090439,-3.64829 8.049329,0 8.04933,0 4.883685,3.48882 c 3.894822,2.78239 4.926318,3.46219 5.094241,3.35732 0.115806,-0.0723 2.325191,-1.64229 4.909744,-3.48882 l 4.699189,-3.35732 8.052119,0 8.052118,0 -0.510624,0.36756 c -0.280842,0.20216 -5.931036,4.24862 -12.555984,8.99213 -6.624949,4.7435 -12.222114,8.75517 -12.438144,8.91481 L 72,126.84208 64.14433,121.20799 Z"
+ id="path3748"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 58.890373,26.058333 0,-3.404124 3.665979,0 3.66598,0 0,3.404124 0,3.404124 -3.66598,0 -3.665979,0 0,-3.404124 z"
+ id="path5455"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 21.445012,45.697508 0,-3.404124 3.66598,0 3.665979,0 0,3.404124 0,3.404124 -3.665979,0 -3.66598,0 0,-3.404124 z"
+ id="path5482"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /><path
+ style="fill:#999999;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 40.29862,45.697508 0,-3.404124 3.66598,0 3.665979,0 0,3.404124 0,3.404124 -3.665979,0 -3.66598,0 0,-3.404124 z"
+ id="path5484"
+ inkscape:connector-curvature="0"
+ transform="translate(-427,87)" /></g></g></svg> \ No newline at end of file
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/search-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/search-868482.svg
new file mode 100644
index 0000000..6ee0ba9
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/search-868482.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="-425 77 148 148" enable-background="new -425 77 148 148" xml:space="preserve">
+<g>
+ <rect x="-425" y="77" fill="none" width="148" height="148"/>
+ <g>
+ <path fill="#868482" d="M-278.2,209.7c1.6,1.6,1.6,4.1,0,5.7l-8.5,8.5c-1.6,1.6-4.1,1.6-5.7,0l-44.6-44.6c-1.6-1.6-1.6-4.1,0-5.7
+ l8.5-8.5c1.6-1.6,4.1-1.6,5.7,0L-278.2,209.7z"/>
+ <path fill="#868482" d="M-367,89c25.4,0,46,20.6,46,46s-20.6,46-46,46c-25.4,0-46-20.6-46-46S-392.4,89-367,89 M-367,77
+ c-32,0-58,26-58,58s26,58,58,58c32,0,58-26,58-58S-335,77-367,77L-367,77z"/>
+ </g>
+</g>
+</svg>
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-80c342.png b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-80c342.png
new file mode 100644
index 0000000..a864a6e
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-80c342.png
Binary files differ
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-868482.svg
new file mode 100644
index 0000000..f0ce693
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-868482.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="-427 84 144 134" enable-background="new -427 84 144 134" xml:space="preserve">
+<g>
+ <rect x="-427" y="84" fill="none" width="144" height="134"/>
+ <g>
+ <path fill="#868482" d="M-323.4,218h-63.4v-56.5H-427l71.9-77.5l71.9,77.5h-40.2L-323.4,218L-323.4,218z M-375.3,206.5h40.5v-56.5
+ h25.4l-45.7-49.2l-45.7,49.2h25.4L-375.3,206.5L-375.3,206.5z"/>
+ </g>
+</g>
+</svg>
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-c5d6b6.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-c5d6b6.svg
new file mode 100644
index 0000000..6cfc345
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/shift-c5d6b6.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="-427 84 144 134" enable-background="new -427 84 144 134" xml:space="preserve">
+<g>
+ <rect x="-427" y="84" fill="none" width="144" height="134"/>
+ <g>
+ <path fill="#C5D6B6" d="M-323.4,218h-63.4v-56.5H-427l71.9-77.5l71.9,77.5h-40.2L-323.4,218L-323.4,218z M-375.3,206.5h40.5v-56.5
+ h25.4l-45.7-49.2l-45.7,49.2h25.4L-375.3,206.5L-375.3,206.5z"/>
+ </g>
+</g>
+</svg>
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/textmode-868482.svg b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/textmode-868482.svg
new file mode 100644
index 0000000..16b4071
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/images/textmode-868482.svg
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="124px"
+ height="96px"
+ viewBox="0 0 124 96"
+ enable-background="new 0 0 124 96"
+ xml:space="preserve"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="textmode-868482.svg"><metadata
+ id="metadata3875"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs3873" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1136"
+ id="namedview3871"
+ showgrid="false"
+ inkscape:zoom="2.4583333"
+ inkscape:cx="-2.4745771"
+ inkscape:cy="47.999999"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Layer_1" /><g
+ id="g3853"
+ style="fill:#999999;fill-opacity:1"><g
+ id="g3855"
+ style="fill:#999999;fill-opacity:1"><g
+ id="g3857"
+ style="fill:#999999;fill-opacity:1"><path
+ fill="#868482"
+ d="M55.4,70.8L46.9,49H19.4L11,70.8H2.9L30,2h6.7l27,68.8H55.4z M44.4,41.8l-8-21.2c-1-2.7-2.1-6-3.2-9.9 c-0.7,3-1.7,6.3-3,9.9l-8.1,21.2H44.4z"
+ id="path3859"
+ style="fill:#999999;fill-opacity:1" /><path
+ fill="#868482"
+ d="M66.6,72.8H54.1L45.5,51H20.8l-8.4,21.8H0L28.7,0h9.4L66.6,72.8z M56.8,68.8h4L35.4,4h-1.9l1.7,6.2 c1.1,3.8,2.1,7.1,3.1,9.7l9,24h-28l9.1-23.9c1.2-3.5,2.2-6.7,2.9-9.6L32.8,4h-1.4L5.9,68.8h3.8L18.1,47h30.2L56.8,68.8z M25.1,39.8h16.4l-7-18.5c-0.4-1.1-0.8-2.2-1.2-3.4c-0.4,1.1-0.7,2.2-1.2,3.4L25.1,39.8z"
+ id="path3861"
+ style="fill:#999999;fill-opacity:1" /></g><g
+ id="g3863"
+ style="fill:#999999;fill-opacity:1"><path
+ fill="#868482"
+ d="M116.2,70.8l-1.5-7.3h-0.4c-2.6,3.2-5.1,5.4-7.7,6.5s-5.7,1.7-9.5,1.7c-5.1,0-9.1-1.3-12-3.9 s-4.3-6.4-4.3-11.2c0-10.4,8.3-15.8,24.9-16.3l8.7-0.3v-3.2c0-4-0.9-7-2.6-8.9s-4.5-2.9-8.3-2.9c-4.3,0-9.1,1.3-14.5,3.9l-2.4-6 c2.5-1.4,5.3-2.5,8.3-3.2s6-1.2,9.1-1.2c6.1,0,10.7,1.4,13.6,4.1s4.4,7.1,4.4,13.1v35.1H116.2z M98.7,65.3c4.8,0,8.6-1.3,11.4-4 s4.1-6.4,4.1-11.2v-4.6l-7.8,0.3c-6.2,0.2-10.6,1.2-13.4,2.9S89,53.1,89,56.7c0,2.8,0.9,5,2.6,6.4S95.6,65.3,98.7,65.3z"
+ id="path3865"
+ style="fill:#999999;fill-opacity:1" /><path
+ fill="#868482"
+ d="M97.1,73.8c-5.6,0-10.1-1.5-13.3-4.5c-3.3-3-5-7.3-5-12.7c0-11.6,9-17.8,26.8-18.3l6.8-0.2v-1.3 c0-3.5-0.7-6.1-2.1-7.6c-1.3-1.5-3.6-2.2-6.8-2.2c-4,0-8.6,1.3-13.7,3.7l-1.9,0.9L84,22.1l1.6-0.8c2.7-1.4,5.6-2.6,8.8-3.4 c3.2-0.8,6.4-1.2,9.6-1.2c6.6,0,11.7,1.6,15,4.6c3.4,3.1,5.1,8,5.1,14.5v37.1h-9.4l-1.1-5.3c-2,2-4,3.5-6,4.4 C104.7,73.1,101.2,73.8,97.1,73.8z M103.5,23c4.4,0,7.7,1.2,9.8,3.5c2.1,2.3,3.1,5.7,3.1,10.3V42l-10.7,0.3 c-23,0.7-23,10.9-23,14.3c0,4.3,1.2,7.5,3.7,9.7c2.5,2.3,6.1,3.4,10.6,3.4c3.5,0,6.4-0.5,8.7-1.5c2.2-1,4.6-3,6.9-6l0.6-0.8h2.6 l0.7,1.6l1.2,5.7h2.1V35.8c0-5.4-1.3-9.3-3.8-11.6c-2.6-2.4-6.7-3.5-12.3-3.5c-2.8,0-5.7,0.4-8.6,1.1c-2.2,0.6-4.3,1.3-6.3,2.3 l0.9,2.3C94.9,24.1,99.4,23,103.5,23z M98.7,67.3c-3.5,0-6.4-0.9-8.5-2.7C88,62.8,87,60.1,87,56.7c0-4.3,1.7-7.6,5-9.6 c3.1-1.9,7.8-3,14.4-3.2l9.9-0.4v6.7c0,5.3-1.6,9.6-4.8,12.6C108.3,65.8,104,67.3,98.7,67.3z M112.2,47.6l-5.7,0.2 c-5.8,0.2-10,1.1-12.4,2.6C92,51.8,91,53.8,91,56.7c0,2.2,0.6,3.8,1.9,4.9c1.3,1.1,3.3,1.7,5.8,1.7c4.3,0,7.6-1.1,10-3.4 c2.4-2.3,3.5-5.5,3.5-9.7V47.6z"
+ id="path3867"
+ style="fill:#999999;fill-opacity:1" /></g></g><rect
+ y="88"
+ fill="#868482"
+ width="124"
+ height="8"
+ id="rect3869"
+ style="fill:#999999;fill-opacity:1" /></g><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 0.33220339,72.63421 c 0,-0.155512 11.21134461,-28.667467 28.36096261,-72.12573542 0.143964,-0.36481583 1.481288,-0.50697527 4.733406,-0.50316785 L 37.959322,0.01061345 51.99322,35.862443 c 7.718644,19.718506 14.093085,36.099169 14.165419,36.401472 0.105888,0.442511 -1.021912,0.549644 -5.786164,0.549644 l -5.917684,0 -0.546838,-1.118644 C 53.607192,71.079661 51.634697,66.138911 49.524625,60.715473 l -3.836489,-9.860803 -12.536913,0.09809 -12.536911,0.09809 -4.160608,10.779661 -4.160608,10.779661 -5.9804461,0.112569 c -3.2892456,0.06192 -5.98044651,0.02208 -5.98044651,-0.08853 z M 41.423311,39.559322 c 0.0112,-0.536844 -7.930409,-21.643254 -8.141955,-21.638878 -0.210051,0.0043 -8.141912,21.095451 -8.137865,21.638878 0.003,0.398954 16.271502,0.398954 16.27982,0 z"
+ id="path3877"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 92.065151,73.149063 c -3.134892,-0.597811 -6.806633,-2.545615 -8.728039,-4.630092 -3.392162,-3.680063 -4.988275,-9.313558 -4.123086,-14.552476 0.655241,-3.967636 1.662266,-6.021269 4.194145,-8.553147 4.290577,-4.290579 10.117905,-6.121781 21.824109,-6.858095 l 7.47634,-0.470258 -0.23843,-2.843927 c -0.31037,-3.702079 -1.57377,-6.208129 -3.6811,-7.301736 -3.65637,-1.897491 -10.292169,-1.160169 -17.463875,1.940458 -1.80721,0.781333 -3.322385,1.379711 -3.367056,1.329729 -0.04467,-0.04998 -0.915507,-2.104434 -1.935193,-4.565451 l -1.853974,-4.474576 2.725673,-1.292565 c 3.14265,-1.490302 7.040665,-2.780454 10.251098,-3.392873 3.029187,-0.577844 10.434727,-0.568505 13.314347,0.01679 7.53165,1.530841 11.84608,6.107198 13.11198,13.90799 0.24028,1.480703 0.41628,10.734302 0.41806,21.980995 l 0.003,19.423728 -4.60617,0 -4.60616,0 -0.46374,-2.493636 c -0.25506,-1.371499 -0.554,-2.583889 -0.6643,-2.694191 -0.11031,-0.110307 -1.04828,0.545637 -2.08439,1.457658 -1.03611,0.91202 -2.66587,2.03679 -3.62169,2.499498 -3.64892,1.766412 -11.019819,2.493295 -15.881619,1.566175 z M 106.05095,61.766929 c 4.32066,-2.196863 6.139,-5.519149 6.14339,-11.224556 l 0.002,-2.949153 -3.76271,0.0081 c -2.06949,0.0044 -5.04407,0.190591 -6.61017,0.413687 -8.020819,1.142591 -10.808919,3.331507 -10.833665,8.505426 -0.02458,5.139533 2.569947,7.10421 8.959187,6.784237 2.870148,-0.143735 3.841638,-0.388564 6.101698,-1.5377 z"
+ id="path3879"
+ inkscape:connector-curvature="0" /><path
+ style="fill:#999999;fill-opacity:1"
+ d="m 0.33220339,92.135593 0,-3.864407 61.83050861,0 61.830508,0 0,3.864407 0,3.864407 -61.830508,0 -61.83050861,0 0,-3.864407 z"
+ id="path3881"
+ inkscape:connector-curvature="0" /></svg> \ No newline at end of file
diff --git a/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/style.qml b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/style.qml
new file mode 100644
index 0000000..9d140d0
--- /dev/null
+++ b/imports/shared/QtQuick/VirtualKeyboard/Styles/automotive/style.qml
@@ -0,0 +1,888 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.VirtualKeyboard 2.1
+import QtQuick.VirtualKeyboard.Styles 2.1
+
+import utils 1.0 as Utils
+
+KeyboardStyle {
+ id: currentStyle
+ readonly property bool compactSelectionList: [InputEngine.Pinyin, InputEngine.Cangjie].indexOf(InputContext.inputEngine.inputMode) !== -1
+ readonly property string fontFamily: Utils.Style.fontFamily
+ readonly property real keyBackgroundMargin: Math.round(13 * scaleHint)
+ readonly property real keyContentMargin: Math.round(45 * scaleHint)
+ readonly property real keyIconScale: scaleHint * 0.6
+ readonly property string resourcePrefix: ""
+
+ readonly property string inputLocale: InputContext.locale
+ property color inputLocaleIndicatorColor: "white"
+ property Timer inputLocaleIndicatorHighlightTimer: Timer {
+ interval: 1000
+ onTriggered: inputLocaleIndicatorColor = "gray"
+ }
+ onInputLocaleChanged: {
+ inputLocaleIndicatorColor = "white"
+ inputLocaleIndicatorHighlightTimer.restart()
+ }
+
+ keyboardDesignWidth: 2560
+ keyboardDesignHeight: 800
+ keyboardRelativeLeftMargin: 114 / keyboardDesignWidth
+ keyboardRelativeRightMargin: 114 / keyboardDesignWidth
+ keyboardRelativeTopMargin: 13 / keyboardDesignHeight
+ keyboardRelativeBottomMargin: 86 / keyboardDesignHeight
+
+ keyboardBackground: Rectangle {
+ color: "black"
+ opacity: 0.9
+ }
+
+ keyPanel: KeyPanel {
+ Rectangle {
+ id: keyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#262a32"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Text {
+ id: keySmallText
+ text: control.smallText
+ visible: control.smallTextVisible
+ color: "gray"
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.margins: keyContentMargin / 3
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 38 * scaleHint
+ capitalization: control.uppercased ? Font.AllUppercase : Font.MixedCase
+ }
+ }
+ Text {
+ id: keyText
+ text: control.displayText
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.fill: parent
+ anchors.leftMargin: keyContentMargin
+ anchors.topMargin: control.smallTextVisible ? keyContentMargin * 1.2 : keyContentMargin
+ anchors.rightMargin: keyContentMargin
+ anchors.bottomMargin: control.smallTextVisible ? keyContentMargin * 0.8 : keyContentMargin
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 52 * scaleHint
+ capitalization: control.uppercased ? Font.AllUppercase : Font.MixedCase
+ }
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: keyBackground
+ opacity: 0.75
+ }
+ PropertyChanges {
+ target: keyText
+ opacity: 0.5
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: keyBackground
+ opacity: 0.75
+ }
+ PropertyChanges {
+ target: keyText
+ opacity: 0.05
+ }
+ }
+ ]
+ }
+
+ backspaceKeyPanel: KeyPanel {
+ Rectangle {
+ id: backspaceKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#14161b"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Image {
+ id: backspaceKeyIcon
+ anchors.centerIn: parent
+ sourceSize.width: 159 * keyIconScale
+ sourceSize.height: 88 * keyIconScale
+ smooth: false
+ source: resourcePrefix + "images/backspace-868482.svg"
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: backspaceKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: backspaceKeyIcon
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: backspaceKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: backspaceKeyIcon
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
+ languageKeyPanel: KeyPanel {
+ Rectangle {
+ id: languageKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#14161b"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Image {
+ id: languageKeyIcon
+ anchors.centerIn: parent
+ sourceSize.width: 144 * keyIconScale
+ sourceSize.height: 144 * keyIconScale
+ smooth: false
+ source: resourcePrefix + "images/globe-868482.svg"
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: languageKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: languageKeyIcon
+ opacity: 0.75
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: languageKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: languageKeyIcon
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
+ enterKeyPanel: KeyPanel {
+ Rectangle {
+ id: enterKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#14161b"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Image {
+ id: enterKeyIcon
+ visible: enterKeyText.text.length === 0
+ anchors.centerIn: parent
+ readonly property size enterKeyIconSize: {
+ switch (control.actionId) {
+ case EnterKeyAction.Go:
+ case EnterKeyAction.Send:
+ case EnterKeyAction.Next:
+ case EnterKeyAction.Done:
+ return Qt.size(170, 119)
+ case EnterKeyAction.Search:
+ return Qt.size(148, 148)
+ default:
+ return Qt.size(211, 80)
+ }
+ }
+ sourceSize.width: enterKeyIconSize.width * keyIconScale
+ sourceSize.height: enterKeyIconSize.height * keyIconScale
+ smooth: false
+ source: {
+ switch (control.actionId) {
+ case EnterKeyAction.Go:
+ case EnterKeyAction.Send:
+ case EnterKeyAction.Next:
+ case EnterKeyAction.Done:
+ return resourcePrefix + "images/check-868482.svg"
+ case EnterKeyAction.Search:
+ return resourcePrefix + "images/search-868482.svg"
+ default:
+ return resourcePrefix + "images/enter-868482.svg"
+ }
+ }
+ }
+ Text {
+ id: enterKeyText
+ visible: text.length !== 0
+ text: control.actionId !== EnterKeyAction.None ? "" : control.displayText
+ clip: true
+ fontSizeMode: Text.HorizontalFit
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ color: "#80c342"
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 44 * scaleHint
+ capitalization: Font.AllUppercase
+ }
+ anchors.fill: parent
+ anchors.margins: Math.round(42 * scaleHint)
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: enterKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: enterKeyIcon
+ opacity: 0.6
+ }
+ PropertyChanges {
+ target: enterKeyText
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: enterKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: enterKeyIcon
+ opacity: 0.2
+ }
+ PropertyChanges {
+ target: enterKeyText
+ opacity: 0.05
+ }
+ }
+ ]
+ }
+
+ hideKeyPanel: KeyPanel {
+ Rectangle {
+ id: hideKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#14161b"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Image {
+ id: hideKeyIcon
+ anchors.centerIn: parent
+ sourceSize.width: 144 * keyIconScale
+ sourceSize.height: 127 * keyIconScale
+ smooth: false
+ source: resourcePrefix + "images/hidekeyboard-868482.svg"
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: hideKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: hideKeyIcon
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: hideKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: hideKeyIcon
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
+ shiftKeyPanel: KeyPanel {
+ Rectangle {
+ id: shiftKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#14161b"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Image {
+ id: shiftKeyIcon
+ anchors.centerIn: parent
+ sourceSize.width: 144 * keyIconScale
+ sourceSize.height: 134 * keyIconScale
+ smooth: false
+ source: resourcePrefix + "images/shift-868482.svg"
+ }
+ states: [
+ State {
+ name: "capslock"
+ when: InputContext.capsLock
+ PropertyChanges {
+ target: shiftKeyBackground
+ color: Utils.Style.colorPink
+ }
+ PropertyChanges {
+ target: shiftKeyIcon
+ source: resourcePrefix + "images/shift-c5d6b6.svg"
+ }
+ },
+ State {
+ name: "shift"
+ when: InputContext.shift
+ PropertyChanges {
+ target: shiftKeyIcon
+ source: resourcePrefix + "images/shift-80c342.png"
+ }
+ }
+ ]
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: shiftKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: shiftKeyIcon
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: shiftKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: shiftKeyIcon
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
+ spaceKeyPanel: KeyPanel {
+ Rectangle {
+ id: spaceKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#14161b"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Text {
+ id: spaceKeyText
+ text: Qt.locale(InputContext.locale).nativeLanguageName
+ color: currentStyle.inputLocaleIndicatorColor
+ Behavior on color { PropertyAnimation { duration: 250 } }
+ anchors.centerIn: parent
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 48 * scaleHint
+ }
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: spaceKeyBackground
+ opacity: 0.80
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: spaceKeyBackground
+ opacity: 0.8
+ }
+ }
+ ]
+ }
+
+ symbolKeyPanel: KeyPanel {
+ Rectangle {
+ id: symbolKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#14161b"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Text {
+ id: symbolKeyText
+ text: control.displayText
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.fill: parent
+ anchors.margins: keyContentMargin
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 44 * scaleHint
+ capitalization: Font.AllUppercase
+ }
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: symbolKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: symbolKeyText
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: symbolKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: symbolKeyText
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
+ modeKeyPanel: KeyPanel {
+ Rectangle {
+ id: modeKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#1e1b18"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Text {
+ id: modeKeyText
+ text: control.displayText
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.fill: parent
+ anchors.margins: keyContentMargin
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 44 * scaleHint
+ capitalization: Font.AllUppercase
+ }
+ }
+ Rectangle {
+ id: modeKeyIndicator
+ implicitHeight: parent.height * 0.1
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.leftMargin: parent.width * 0.4
+ anchors.rightMargin: parent.width * 0.4
+ anchors.bottomMargin: parent.height * 0.12
+ color: "#80c342"
+ radius: Utils.Style.buttonRadius
+ visible: control.mode
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: modeKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: modeKeyText
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: modeKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: modeKeyText
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
+ handwritingKeyPanel: KeyPanel {
+ Rectangle {
+ id: hwrKeyBackground
+ radius: Utils.Style.buttonRadius
+ color: "#35322f"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Image {
+ id: hwrKeyIcon
+ anchors.centerIn: parent
+ readonly property size hwrKeyIconSize: keyboard.handwritingMode ? Qt.size(124, 96) : Qt.size(156, 104)
+ sourceSize.width: hwrKeyIconSize.width * keyIconScale
+ sourceSize.height: hwrKeyIconSize.height * keyIconScale
+ smooth: false
+ source: resourcePrefix + (keyboard.handwritingMode ? "images/textmode-868482.svg" : "images/handwriting-868482.svg")
+ }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: control.pressed
+ PropertyChanges {
+ target: hwrKeyBackground
+ opacity: 0.80
+ }
+ PropertyChanges {
+ target: hwrKeyIcon
+ opacity: 0.6
+ }
+ },
+ State {
+ name: "disabled"
+ when: !control.enabled
+ PropertyChanges {
+ target: hwrKeyBackground
+ opacity: 0.8
+ }
+ PropertyChanges {
+ target: hwrKeyIcon
+ opacity: 0.2
+ }
+ }
+ ]
+ }
+
+ characterPreviewMargin: 0
+ characterPreviewDelegate: Item {
+ property string text
+ id: characterPreview
+ Rectangle {
+ id: characterPreviewBackground
+ anchors.fill: parent
+ color: "#262a32"
+ radius: Utils.Style.buttonRadius
+ Text {
+ id: characterPreviewText
+ color: "white"
+ text: characterPreview.text
+ fontSizeMode: Text.HorizontalFit
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.fill: parent
+ anchors.margins: Math.round(48 * scaleHint)
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 82 * scaleHint
+ }
+ }
+ }
+ }
+
+ alternateKeysListItemWidth: 99 * scaleHint
+ alternateKeysListItemHeight: 150 * scaleHint
+ alternateKeysListDelegate: Item {
+ id: alternateKeysListItem
+ width: alternateKeysListItemWidth
+ height: alternateKeysListItemHeight
+ Text {
+ id: listItemText
+ text: model.text
+ color: "#262a32"
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 52 * scaleHint
+ }
+ anchors.centerIn: parent
+ }
+ states: State {
+ name: "current"
+ when: alternateKeysListItem.ListView.isCurrentItem
+ PropertyChanges {
+ target: listItemText
+ color: "white"
+ }
+ }
+ }
+ alternateKeysListHighlight: Rectangle {
+ color: "#262a32"
+ radius: Utils.Style.buttonRadius
+ }
+ alternateKeysListBackground: Rectangle {
+ color: "#14161b"
+ radius: Utils.Style.buttonRadius
+ }
+
+ selectionListHeight: 85 * scaleHint
+ selectionListDelegate: SelectionListItem {
+ id: selectionListItem
+ width: Math.round(selectionListLabel.width + selectionListLabel.anchors.leftMargin * 2)
+ Text {
+ id: selectionListLabel
+ anchors.left: parent.left
+ anchors.leftMargin: Math.round((compactSelectionList ? 50 : 140) * scaleHint)
+ anchors.verticalCenter: parent.verticalCenter
+ text: decorateText(display, wordCompletionLength)
+ color: "#BC6608"
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 44 * scaleHint
+ }
+ function decorateText(text, wordCompletionLength) {
+ if (wordCompletionLength > 0) {
+ return text.slice(0, -wordCompletionLength) + '<u>' + text.slice(-wordCompletionLength) + '</u>'
+ }
+ return text
+ }
+ }
+ Rectangle {
+ id: selectionListSeparator
+ width: 4 * scaleHint
+ height: 36 * scaleHint
+ radius: 2
+ color: "#35322f"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.left
+ }
+ states: State {
+ name: "current"
+ when: selectionListItem.ListView.isCurrentItem
+ PropertyChanges {
+ target: selectionListLabel
+ color: "white"
+ }
+ }
+ }
+ selectionListBackground: keyboardBackground
+
+ selectionListAdd: Transition {
+ NumberAnimation { property: "y"; from: wordCandidateView.height; duration: 200 }
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200 }
+ }
+ selectionListRemove: Transition {
+ NumberAnimation { property: "y"; to: -wordCandidateView.height; duration: 200 }
+ NumberAnimation { property: "opacity"; to: 0; duration: 200 }
+ }
+
+ navigationHighlight: Rectangle {
+ color: "transparent"
+ border.color: "yellow"
+ border.width: 5
+ }
+
+ traceInputKeyPanelDelegate: TraceInputKeyPanel {
+ traceMargins: keyBackgroundMargin
+ Rectangle {
+ id: traceInputKeyPanelBackground
+ radius: Utils.Style.buttonRadius
+ color: "#35322f"
+ anchors.fill: parent
+ anchors.margins: keyBackgroundMargin
+ Text {
+ id: hwrInputModeIndicator
+ visible: control.patternRecognitionMode === InputEngine.HandwritingRecoginition
+ text: InputContext.inputEngine.inputMode === InputEngine.Latin ? "Abc" : "123"
+ color: "white"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: keyContentMargin
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: 44 * scaleHint
+ capitalization: {
+ if (InputContext.capsLock)
+ return Font.AllUppercase
+ if (InputContext.shift)
+ return Font.MixedCase
+ return Font.AllLowercase
+ }
+ }
+ }
+ }
+ Canvas {
+ id: traceInputKeyGuideLines
+ anchors.fill: traceInputKeyPanelBackground
+ opacity: 0.1
+ onPaint: {
+ console.error("PAINT")
+ var ctx = getContext("2d")
+ ctx.lineWidth = 1
+ ctx.strokeStyle = "#BC6608"
+ ctx.clearRect(0, 0, width, height)
+ var i
+ if (control.horizontalRulers) {
+ for (i = 0; i < control.horizontalRulers.length; i++) {
+ ctx.beginPath()
+ ctx.moveTo(0, control.horizontalRulers[i])
+ ctx.lineTo(width, control.horizontalRulers[i])
+ ctx.stroke()
+ }
+ }
+ if (control.verticalRulers) {
+ for (i = 0; i < control.verticalRulers.length; i++) {
+ ctx.beginPath()
+ ctx.moveTo(control.verticalRulers[i], 0)
+ ctx.lineTo(control.verticalRulers[i], height)
+ ctx.stroke()
+ }
+ }
+ }
+ }
+ }
+
+ traceCanvasDelegate: TraceCanvas {
+ id: traceCanvas
+ onAvailableChanged: {
+ if (!available)
+ return
+ var ctx = getContext("2d")
+ if (parent.canvasType === "fullscreen") {
+ ctx.lineWidth = 10
+ ctx.strokeStyle = "#BC6608"
+ } else {
+ ctx.lineWidth = 10 * scaleHint
+ ctx.strokeStyle = "#BC6608"
+ }
+ ctx.lineCap = "round"
+ ctx.fillStyle = ctx.strokeStyle
+ }
+ autoDestroyDelay: 800
+ onTraceChanged: if (trace === null) opacity = 0
+ Behavior on opacity { PropertyAnimation { easing.type: Easing.OutCubic; duration: 150 } }
+ }
+
+ popupListDelegate: SelectionListItem {
+ property real cursorAnchor: popupListLabel.x + popupListLabel.width
+ id: popupListItem
+ width: popupListLabel.width + popupListLabel.anchors.leftMargin * 2
+ height: popupListLabel.height + popupListLabel.anchors.topMargin * 2
+ Text {
+ id: popupListLabel
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.leftMargin: popupListLabel.height / 2
+ anchors.topMargin: popupListLabel.height / 3
+ text: decorateText(display, wordCompletionLength)
+ color: "#5CAA15"
+ font {
+ family: fontFamily
+ weight: Utils.Style.fontWeight
+ pixelSize: Qt.inputMethod.cursorRectangle.height * 0.8
+ }
+ function decorateText(text, wordCompletionLength) {
+ if (wordCompletionLength > 0) {
+ return text.slice(0, -wordCompletionLength) + '<u>' + text.slice(-wordCompletionLength) + '</u>'
+ }
+ return text
+ }
+ }
+ states: State {
+ name: "current"
+ when: popupListItem.ListView.isCurrentItem
+ PropertyChanges {
+ target: popupListLabel
+ color: "black"
+ }
+ }
+ }
+
+ popupListBackground: Item {
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ color: "white"
+ border {
+ width: 1
+ color: "#929495"
+ }
+ }
+ }
+
+ popupListAdd: Transition {
+ NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 200 }
+ }
+
+ popupListRemove: Transition {
+ NumberAnimation { property: "opacity"; to: 0; duration: 200 }
+ }
+}
diff --git a/imports/shared/assets/drawable-ldpi/FloatingButton_Active.svg b/imports/shared/assets/drawable-ldpi/FloatingButton_Active.svg
new file mode 100644
index 0000000..ef10835
--- /dev/null
+++ b/imports/shared/assets/drawable-ldpi/FloatingButton_Active.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="390px" height="390px" viewBox="0 0 390 390" style="enable-background:new 0 0 390 390;" xml:space="preserve">
+<style type="text/css">
+ .st0{opacity:0.3;enable-background:new ;}
+ .st1{opacity:0.5;}
+ .st2{fill:#FFFFFF;}
+ .st3{fill:#5CAA15;}
+ .st4{fill:none;}
+</style>
+<g id="Active">
+ <g>
+ <circle class="st0" cx="195" cy="195" r="191"/>
+ <g class="st1">
+ <path class="st2" d="M195,4c105.5,0,191,85.5,191,191s-85.5,191-191,191S4,300.5,4,195S89.5,4,195,4 M195,0
+ c-26.3,0-51.9,5.2-75.9,15.3c-23.2,9.8-44.1,23.9-62,41.8s-32,38.8-41.8,62C5.2,143.1,0,168.7,0,195s5.2,51.9,15.3,75.9
+ c9.8,23.2,23.9,44.1,41.8,62s38.8,32,62,41.8c24,10.2,49.6,15.3,75.9,15.3s51.9-5.2,75.9-15.3c23.2-9.8,44.1-23.9,62-41.8
+ s32-38.8,41.8-62c10.2-24,15.3-49.6,15.3-75.9s-5.2-51.9-15.3-75.9c-9.8-23.2-23.9-44.1-41.8-62s-38.8-32-62-41.8
+ C246.9,5.2,221.3,0,195,0L195,0z"/>
+ </g>
+ </g>
+ <circle class="st3" cx="195" cy="195" r="141"/>
+</g>
+<g id="icon">
+ <g>
+ <g>
+ <path class="st2" d="M155.6,247.3c-10.1,0-18.9-5-23.1-13.6c-10.1-21,5.4-37.4,21.7-54.7c1.2-1.2,2.4-2.5,3.6-3.8
+ c5.3-5.7,5.2-11.5,3.5-14.8c-1.8-3.4-5.5-4.9-10.2-4.2c-16.5,2.6-21.2,26.4-21.2,26.6l-11.9-2.2c0.3-1.3,6.4-32.3,31.2-36.3
+ c9.8-1.6,18.5,2.4,22.7,10.4c4.7,8.9,2.6,20.1-5.3,28.6c-1.2,1.3-2.4,2.6-3.6,3.8c-16.7,17.8-25.9,28.5-19.6,41.4
+ c3.3,6.8,11.1,7.6,16.9,6.3c9.2-2.1,19.8-11.1,19.7-29.5c-0.2-28.1,16.2-41.8,30.2-44.9c14.5-3.2,28.4,3.6,34.7,17
+ c1.3,2.8,2.3,5.4,3.1,8.1c13.3,0.7,25.5,4.3,26,4.4l-3.4,11.5c-0.1,0-9.7-2.8-20.6-3.8c0.5,16.5-8.6,28.9-20.1,34.7
+ c-11.9,6-24,3.8-28.9-5.2c-3.1-5.6-1.9-14.7,2.9-22.5c7.9-13,21.3-17.4,31.5-18.8c-0.4-1.2-0.9-2.4-1.4-3.4
+ c-3.9-8.3-12.2-12.4-21.1-10.4c-9.7,2.2-21,12.1-20.8,33.1c0.2,25.5-15.6,38.1-29,41.3C160.5,247,158,247.3,155.6,247.3z
+ M237.8,197.7c-14,1.5-20.6,8.5-23.4,12.9c-3.3,5.2-3.4,9.8-2.9,10.9c1.6,2.9,7.3,3,13,0.2C235.3,216.2,238.3,206.6,237.8,197.7z
+ "/>
+ </g>
+ <rect x="118" y="144" class="st4" width="156" height="104"/>
+ </g>
+</g>
+</svg>
diff --git a/imports/shared/assets/drawable-ldpi/FloatingButton_Available.svg b/imports/shared/assets/drawable-ldpi/FloatingButton_Available.svg
new file mode 100644
index 0000000..1178c8c
--- /dev/null
+++ b/imports/shared/assets/drawable-ldpi/FloatingButton_Available.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="390px" height="390px" viewBox="0 0 390 390" style="enable-background:new 0 0 390 390;" xml:space="preserve">
+<style type="text/css">
+ .st0{opacity:0.3;enable-background:new ;}
+ .st1{opacity:0.5;}
+ .st2{fill:#FFFFFF;}
+ .st3{fill:#26282A;}
+ .st4{fill:none;}
+</style>
+<g id="Available">
+ <g>
+ <circle class="st0" cx="195" cy="195" r="191"/>
+ <g class="st1">
+ <path class="st2" d="M195,4c105.5,0,191,85.5,191,191s-85.5,191-191,191S4,300.5,4,195S89.5,4,195,4 M195,0
+ c-26.3,0-51.9,5.2-75.9,15.3c-23.2,9.8-44.1,23.9-62,41.8s-32,38.8-41.8,62C5.2,143.1,0,168.7,0,195s5.2,51.9,15.3,75.9
+ c9.8,23.2,23.9,44.1,41.8,62s38.8,32,62,41.8c24,10.2,49.6,15.3,75.9,15.3s51.9-5.2,75.9-15.3c23.2-9.8,44.1-23.9,62-41.8
+ s32-38.8,41.8-62c10.2-24,15.3-49.6,15.3-75.9s-5.2-51.9-15.3-75.9c-9.8-23.2-23.9-44.1-41.8-62s-38.8-32-62-41.8
+ C246.9,5.2,221.3,0,195,0L195,0z"/>
+ </g>
+ </g>
+ <circle class="st3" cx="195" cy="195" r="141"/>
+</g>
+<g id="icon">
+ <g>
+ <g>
+ <path class="st2" d="M155.6,247.3c-10.1,0-18.9-5-23.1-13.6c-10.1-21,5.4-37.4,21.7-54.7c1.2-1.2,2.4-2.5,3.6-3.8
+ c5.3-5.7,5.2-11.5,3.5-14.8c-1.8-3.4-5.5-4.9-10.2-4.2c-16.5,2.6-21.2,26.4-21.2,26.6l-11.9-2.2c0.3-1.3,6.4-32.3,31.2-36.3
+ c9.8-1.6,18.5,2.4,22.7,10.4c4.7,8.9,2.6,20.1-5.3,28.6c-1.2,1.3-2.4,2.6-3.6,3.8c-16.7,17.8-25.9,28.5-19.6,41.4
+ c3.3,6.8,11.1,7.6,16.9,6.3c9.2-2.1,19.8-11.1,19.7-29.5c-0.2-28.1,16.2-41.8,30.2-44.9c14.5-3.2,28.4,3.6,34.7,17
+ c1.3,2.8,2.3,5.4,3.1,8.1c13.3,0.7,25.5,4.3,26,4.4l-3.4,11.5c-0.1,0-9.7-2.8-20.6-3.8c0.5,16.5-8.6,28.9-20.1,34.7
+ c-11.9,6-24,3.8-28.9-5.2c-3.1-5.6-1.9-14.7,2.9-22.5c7.9-13,21.3-17.4,31.5-18.8c-0.4-1.2-0.9-2.4-1.4-3.4
+ c-3.9-8.3-12.2-12.4-21.1-10.4c-9.7,2.2-21,12.1-20.8,33.1c0.2,25.5-15.6,38.1-29,41.3C160.5,247,158,247.3,155.6,247.3z
+ M237.8,197.7c-14,1.5-20.6,8.5-23.4,12.9c-3.3,5.2-3.4,9.8-2.9,10.9c1.6,2.9,7.3,3,13,0.2C235.3,216.2,238.3,206.6,237.8,197.7z
+ "/>
+ </g>
+ <rect x="118" y="144" class="st4" width="156" height="104"/>
+ </g>
+</g>
+</svg>
diff --git a/imports/shared/assets/drawable-ldpi/FloatingButton_Unavailable.svg b/imports/shared/assets/drawable-ldpi/FloatingButton_Unavailable.svg
new file mode 100644
index 0000000..d8149b5
--- /dev/null
+++ b/imports/shared/assets/drawable-ldpi/FloatingButton_Unavailable.svg
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="390px" height="390px" viewBox="0 0 390 390" style="enable-background:new 0 0 390 390;" xml:space="preserve">
+<style type="text/css">
+ .st0{opacity:0.3;enable-background:new ;}
+ .st1{opacity:0.5;}
+ .st2{fill:#FFFFFF;}
+ .st3{fill:none;}
+</style>
+<g id="Unavailable">
+ <g>
+ <circle class="st0" cx="195" cy="195" r="191"/>
+ <g class="st1">
+ <path class="st2" d="M195,4c105.5,0,191,85.5,191,191s-85.5,191-191,191S4,300.5,4,195S89.5,4,195,4 M195,0
+ c-26.3,0-51.9,5.2-75.9,15.3c-23.2,9.8-44.1,23.9-62,41.8s-32,38.8-41.8,62C5.2,143.1,0,168.7,0,195s5.2,51.9,15.3,75.9
+ c9.8,23.2,23.9,44.1,41.8,62s38.8,32,62,41.8c24,10.2,49.6,15.3,75.9,15.3s51.9-5.2,75.9-15.3c23.2-9.8,44.1-23.9,62-41.8
+ s32-38.8,41.8-62c10.2-24,15.3-49.6,15.3-75.9s-5.2-51.9-15.3-75.9c-9.8-23.2-23.9-44.1-41.8-62s-38.8-32-62-41.8
+ C246.9,5.2,221.3,0,195,0L195,0z"/>
+ </g>
+ </g>
+</g>
+<g id="icon">
+ <g>
+ <g>
+ <path class="st2" d="M155.6,247.3c-10.1,0-18.9-5-23.1-13.6c-10.1-21,5.4-37.4,21.7-54.7c1.2-1.2,2.4-2.5,3.6-3.8
+ c5.3-5.7,5.2-11.5,3.5-14.8c-1.8-3.4-5.5-4.9-10.2-4.2c-16.5,2.6-21.2,26.4-21.2,26.6l-11.9-2.2c0.3-1.3,6.4-32.3,31.2-36.3
+ c9.8-1.6,18.5,2.4,22.7,10.4c4.7,8.9,2.6,20.1-5.3,28.6c-1.2,1.3-2.4,2.6-3.6,3.8c-16.7,17.8-25.9,28.5-19.6,41.4
+ c3.3,6.8,11.1,7.6,16.9,6.3c9.2-2.1,19.8-11.1,19.7-29.5c-0.2-28.1,16.2-41.8,30.2-44.9c14.5-3.2,28.4,3.6,34.7,17
+ c1.3,2.8,2.3,5.4,3.1,8.1c13.3,0.7,25.5,4.3,26,4.4l-3.4,11.5c-0.1,0-9.7-2.8-20.6-3.8c0.5,16.5-8.6,28.9-20.1,34.7
+ c-11.9,6-24,3.8-28.9-5.2c-3.1-5.6-1.9-14.7,2.9-22.5c7.9-13,21.3-17.4,31.5-18.8c-0.4-1.2-0.9-2.4-1.4-3.4
+ c-3.9-8.3-12.2-12.4-21.1-10.4c-9.7,2.2-21,12.1-20.8,33.1c0.2,25.5-15.6,38.1-29,41.3C160.5,247,158,247.3,155.6,247.3z
+ M237.8,197.7c-14,1.5-20.6,8.5-23.4,12.9c-3.3,5.2-3.4,9.8-2.9,10.9c1.6,2.9,7.3,3,13,0.2C235.3,216.2,238.3,206.6,237.8,197.7z
+ "/>
+ </g>
+ <rect x="118" y="144" class="st3" width="156" height="104"/>
+ </g>
+</g>
+</svg>
diff --git a/imports/shared/assets/icons/4g-signal-strength.png b/imports/shared/assets/icons/4g-signal-strength.png
new file mode 100644
index 0000000..1a90381
--- /dev/null
+++ b/imports/shared/assets/icons/4g-signal-strength.png
Binary files differ
diff --git a/imports/shared/assets/icons/Built_with_Qt_RGB_logo_white.png b/imports/shared/assets/icons/Built_with_Qt_RGB_logo_white.png
new file mode 100644
index 0000000..38300a2
--- /dev/null
+++ b/imports/shared/assets/icons/Built_with_Qt_RGB_logo_white.png
Binary files differ
diff --git a/imports/shared/assets/icons/CarFocusButton.png b/imports/shared/assets/icons/CarFocusButton.png
new file mode 100644
index 0000000..0b2a167
--- /dev/null
+++ b/imports/shared/assets/icons/CarFocusButton.png
Binary files differ
diff --git a/imports/shared/assets/icons/CarInfo.png b/imports/shared/assets/icons/CarInfo.png
new file mode 100644
index 0000000..ad7f0fd
--- /dev/null
+++ b/imports/shared/assets/icons/CarInfo.png
Binary files differ
diff --git a/imports/shared/assets/icons/FullScreenGradient.png b/imports/shared/assets/icons/FullScreenGradient.png
new file mode 100644
index 0000000..417ad98
--- /dev/null
+++ b/imports/shared/assets/icons/FullScreenGradient.png
Binary files differ
diff --git a/imports/shared/assets/icons/Highlight.png b/imports/shared/assets/icons/Highlight.png
new file mode 100644
index 0000000..5f22e74
--- /dev/null
+++ b/imports/shared/assets/icons/Highlight.png
Binary files differ
diff --git a/imports/shared/assets/icons/MapOverlayEdgeGradient.png b/imports/shared/assets/icons/MapOverlayEdgeGradient.png
new file mode 100644
index 0000000..88d99e8
--- /dev/null
+++ b/imports/shared/assets/icons/MapOverlayEdgeGradient.png
Binary files differ
diff --git a/imports/shared/assets/icons/MiddleMask.png b/imports/shared/assets/icons/MiddleMask.png
new file mode 100644
index 0000000..7112637
--- /dev/null
+++ b/imports/shared/assets/icons/MiddleMask.png
Binary files differ
diff --git a/imports/shared/assets/icons/MusicOverlayGradient.png b/imports/shared/assets/icons/MusicOverlayGradient.png
new file mode 100644
index 0000000..b604a23
--- /dev/null
+++ b/imports/shared/assets/icons/MusicOverlayGradient.png
Binary files differ
diff --git a/imports/shared/assets/icons/MusicOverlayGradient2.png b/imports/shared/assets/icons/MusicOverlayGradient2.png
new file mode 100644
index 0000000..da672eb
--- /dev/null
+++ b/imports/shared/assets/icons/MusicOverlayGradient2.png
Binary files differ
diff --git a/imports/shared/assets/icons/NavRoundmarker.png b/imports/shared/assets/icons/NavRoundmarker.png
new file mode 100644
index 0000000..9841616
--- /dev/null
+++ b/imports/shared/assets/icons/NavRoundmarker.png
Binary files differ
diff --git a/imports/shared/assets/icons/RectangleGradient256x512.png b/imports/shared/assets/icons/RectangleGradient256x512.png
new file mode 100644
index 0000000..f83eb63
--- /dev/null
+++ b/imports/shared/assets/icons/RectangleGradient256x512.png
Binary files differ
diff --git a/imports/shared/assets/icons/SimpleBottomBackground.png b/imports/shared/assets/icons/SimpleBottomBackground.png
new file mode 100644
index 0000000..75f28ce
--- /dev/null
+++ b/imports/shared/assets/icons/SimpleBottomBackground.png
Binary files differ
diff --git a/imports/shared/assets/icons/acautosync-knob-down.png b/imports/shared/assets/icons/acautosync-knob-down.png
new file mode 100644
index 0000000..cf0d6ba
--- /dev/null
+++ b/imports/shared/assets/icons/acautosync-knob-down.png
Binary files differ
diff --git a/imports/shared/assets/icons/acautosync-knob-up.png b/imports/shared/assets/icons/acautosync-knob-up.png
new file mode 100644
index 0000000..1996977
--- /dev/null
+++ b/imports/shared/assets/icons/acautosync-knob-up.png
Binary files differ
diff --git a/imports/shared/assets/icons/back-background.png b/imports/shared/assets/icons/back-background.png
new file mode 100644
index 0000000..5e83e7f
--- /dev/null
+++ b/imports/shared/assets/icons/back-background.png
Binary files differ
diff --git a/imports/shared/assets/icons/back.png b/imports/shared/assets/icons/back.png
new file mode 100644
index 0000000..8edc62c
--- /dev/null
+++ b/imports/shared/assets/icons/back.png
Binary files differ
diff --git a/imports/shared/assets/icons/background-contacts.png b/imports/shared/assets/icons/background-contacts.png
new file mode 100644
index 0000000..ce8ee44
--- /dev/null
+++ b/imports/shared/assets/icons/background-contacts.png
Binary files differ
diff --git a/imports/shared/assets/icons/bluetooth.png b/imports/shared/assets/icons/bluetooth.png
new file mode 100644
index 0000000..7d76c79
--- /dev/null
+++ b/imports/shared/assets/icons/bluetooth.png
Binary files differ
diff --git a/imports/shared/assets/icons/calendar.png b/imports/shared/assets/icons/calendar.png
new file mode 100644
index 0000000..cb95cdb
--- /dev/null
+++ b/imports/shared/assets/icons/calendar.png
Binary files differ
diff --git a/imports/shared/assets/icons/cancel.png b/imports/shared/assets/icons/cancel.png
new file mode 100644
index 0000000..b546ab1
--- /dev/null
+++ b/imports/shared/assets/icons/cancel.png
Binary files differ
diff --git a/imports/shared/assets/icons/car-info.png b/imports/shared/assets/icons/car-info.png
new file mode 100644
index 0000000..b6856f0
--- /dev/null
+++ b/imports/shared/assets/icons/car-info.png
Binary files differ
diff --git a/imports/shared/assets/icons/contacts.png b/imports/shared/assets/icons/contacts.png
new file mode 100644
index 0000000..c9b257c
--- /dev/null
+++ b/imports/shared/assets/icons/contacts.png
Binary files differ
diff --git a/imports/shared/assets/icons/destination-airport.png b/imports/shared/assets/icons/destination-airport.png
new file mode 100644
index 0000000..76a7ee2
--- /dev/null
+++ b/imports/shared/assets/icons/destination-airport.png
Binary files differ
diff --git a/imports/shared/assets/icons/destination-home.png b/imports/shared/assets/icons/destination-home.png
new file mode 100644
index 0000000..6581c9f
--- /dev/null
+++ b/imports/shared/assets/icons/destination-home.png
Binary files differ
diff --git a/imports/shared/assets/icons/destination-work.png b/imports/shared/assets/icons/destination-work.png
new file mode 100644
index 0000000..d7959a6
--- /dev/null
+++ b/imports/shared/assets/icons/destination-work.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection-head.png b/imports/shared/assets/icons/fandirection-head.png
new file mode 100644
index 0000000..813d9b1
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection-head.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection-headandlegs.png b/imports/shared/assets/icons/fandirection-headandlegs.png
new file mode 100644
index 0000000..008355f
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection-headandlegs.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection-knob-down.png b/imports/shared/assets/icons/fandirection-knob-down.png
new file mode 100644
index 0000000..f9663ab
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection-knob-down.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection-knob-up.png b/imports/shared/assets/icons/fandirection-knob-up.png
new file mode 100644
index 0000000..cccf882
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection-knob-up.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection-legs.png b/imports/shared/assets/icons/fandirection-legs.png
new file mode 100644
index 0000000..82b06b8
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection-legs.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection-windshield.png b/imports/shared/assets/icons/fandirection-windshield.png
new file mode 100644
index 0000000..7565f24
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection-windshield.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection-windshieldandlegs.png b/imports/shared/assets/icons/fandirection-windshieldandlegs.png
new file mode 100644
index 0000000..c368b20
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection-windshieldandlegs.png
Binary files differ
diff --git a/imports/shared/assets/icons/fandirection.png b/imports/shared/assets/icons/fandirection.png
new file mode 100644
index 0000000..0f47466
--- /dev/null
+++ b/imports/shared/assets/icons/fandirection.png
Binary files differ
diff --git a/imports/shared/assets/icons/jane.png b/imports/shared/assets/icons/jane.png
new file mode 100644
index 0000000..b971522
--- /dev/null
+++ b/imports/shared/assets/icons/jane.png
Binary files differ
diff --git a/imports/shared/assets/icons/john.png b/imports/shared/assets/icons/john.png
new file mode 100644
index 0000000..6099666
--- /dev/null
+++ b/imports/shared/assets/icons/john.png
Binary files differ
diff --git a/imports/shared/assets/icons/music.png b/imports/shared/assets/icons/music.png
new file mode 100644
index 0000000..77bd3df
--- /dev/null
+++ b/imports/shared/assets/icons/music.png
Binary files differ
diff --git a/imports/shared/assets/icons/placeofinterest-charging.png b/imports/shared/assets/icons/placeofinterest-charging.png
new file mode 100644
index 0000000..b3bf6ad
--- /dev/null
+++ b/imports/shared/assets/icons/placeofinterest-charging.png
Binary files differ
diff --git a/imports/shared/assets/icons/placeofinterest-coffee.png b/imports/shared/assets/icons/placeofinterest-coffee.png
new file mode 100644
index 0000000..20bfb4f
--- /dev/null
+++ b/imports/shared/assets/icons/placeofinterest-coffee.png
Binary files differ
diff --git a/imports/shared/assets/icons/placeofinterest-parking.png b/imports/shared/assets/icons/placeofinterest-parking.png
new file mode 100644
index 0000000..922b000
--- /dev/null
+++ b/imports/shared/assets/icons/placeofinterest-parking.png
Binary files differ
diff --git a/imports/shared/assets/icons/placeofinterest-shopping.png b/imports/shared/assets/icons/placeofinterest-shopping.png
new file mode 100644
index 0000000..850d0b5
--- /dev/null
+++ b/imports/shared/assets/icons/placeofinterest-shopping.png
Binary files differ
diff --git a/imports/shared/assets/icons/screencast.png b/imports/shared/assets/icons/screencast.png
new file mode 100644
index 0000000..587f06c
--- /dev/null
+++ b/imports/shared/assets/icons/screencast.png
Binary files differ
diff --git a/imports/shared/assets/icons/search.png b/imports/shared/assets/icons/search.png
new file mode 100644
index 0000000..2c673b5
--- /dev/null
+++ b/imports/shared/assets/icons/search.png
Binary files differ
diff --git a/imports/shared/assets/icons/video-next.png b/imports/shared/assets/icons/video-next.png
new file mode 100644
index 0000000..f529265
--- /dev/null
+++ b/imports/shared/assets/icons/video-next.png
Binary files differ
diff --git a/imports/shared/assets/icons/video-pause.png b/imports/shared/assets/icons/video-pause.png
new file mode 100644
index 0000000..cfe9cc8
--- /dev/null
+++ b/imports/shared/assets/icons/video-pause.png
Binary files differ
diff --git a/imports/shared/assets/icons/video-play.png b/imports/shared/assets/icons/video-play.png
new file mode 100644
index 0000000..8933bb4
--- /dev/null
+++ b/imports/shared/assets/icons/video-play.png
Binary files differ
diff --git a/imports/shared/assets/icons/video-previous.png b/imports/shared/assets/icons/video-previous.png
new file mode 100644
index 0000000..e9aa0de
--- /dev/null
+++ b/imports/shared/assets/icons/video-previous.png
Binary files differ
diff --git a/imports/shared/assets/icons/video.png b/imports/shared/assets/icons/video.png
new file mode 100644
index 0000000..7057d94
--- /dev/null
+++ b/imports/shared/assets/icons/video.png
Binary files differ
diff --git a/imports/shared/assets/icons/wifi-signal-strength.png b/imports/shared/assets/icons/wifi-signal-strength.png
new file mode 100644
index 0000000..61dd6f3
--- /dev/null
+++ b/imports/shared/assets/icons/wifi-signal-strength.png
Binary files differ
diff --git a/imports/shared/controls/AppStackView.qml b/imports/shared/controls/AppStackView.qml
new file mode 100644
index 0000000..d9ec1e1
--- /dev/null
+++ b/imports/shared/controls/AppStackView.qml
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+import QtQuick.Controls 1.0
+import controls 1.0
+import utils 1.0
+
+StackView {
+ id: stack
+
+ delegate: StackViewDelegate {
+ function transitionFinished(properties)
+ {
+ }
+
+ pushTransition: StackViewTransition {
+ id: pushTransition
+ property int duration: 400
+
+
+ PropertyAnimation {
+ target: exitItem
+ property: "x"
+ to: -(2*exitItem.width)
+ duration: pushTransition.duration
+ }
+
+ PropertyAnimation {
+ target: enterItem
+ property: "x"
+ from: 2*enterItem.width
+ to: 0
+ duration: pushTransition.duration
+ }
+ }
+ popTransition: StackViewTransition {
+ id: popTransition
+ property int duration: 250
+
+ PropertyAnimation {
+ target: exitItem
+ property: "x"
+ to: 2*exitItem.width
+ duration: popTransition.duration
+ }
+
+ PropertyAnimation {
+ target: enterItem
+ property: "x"
+ from: -(2*enterItem.width)
+ to: 0
+ duration: popTransition.duration
+ }
+ }
+ }
+ Tracer{}
+}
diff --git a/imports/shared/controls/Button_neptune.qml b/imports/shared/controls/Button_neptune.qml
new file mode 100644
index 0000000..cb01758
--- /dev/null
+++ b/imports/shared/controls/Button_neptune.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtQuick.Layouts 1.0
+
+import utils 1.0
+
+UIElement {
+ id: root
+ vspan: 2
+
+ property alias text: label.text
+ property string iconName
+ property alias label: label
+ property alias icon: icon
+ property alias pressed: mouseArea.pressed
+
+ property int spacing: Style.padding
+
+ signal pressed
+
+ Rectangle {
+ anchors.fill: parent
+ color: '#000'
+ opacity: 0.85
+
+ Behavior on scale { NumberAnimation {} }
+ }
+
+ Column {
+ id: layout
+
+ anchors.centerIn: parent
+
+ spacing: root.spacing
+
+ Image {
+ id: icon
+
+ source: iconName ? Style.symbol(iconName) : ""
+ anchors.horizontalCenter: parent.horizontalCenter
+ visible: source !== undefined
+ asynchronous: true
+ }
+
+ Label {
+ id: label
+ visible: text
+ opacity: root.enabled ? 1.0 : 0.6
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: Style.fontSizeM
+ scale: mouseArea.pressed?0.85:1.0
+ Behavior on scale { NumberAnimation {} }
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+
+ anchors.fill: parent
+ onClicked: root.pressed()
+ }
+}
diff --git a/imports/shared/controls/DisplayBackground.qml b/imports/shared/controls/DisplayBackground.qml
new file mode 100644
index 0000000..ab3a11c
--- /dev/null
+++ b/imports/shared/controls/DisplayBackground.qml
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import QtGraphicalEffects 1.0
+import utils 1.0
+
+Item {
+
+ property string background: Style.displayBackground
+
+ Image {
+ source: Style.symbol("FullScreenGradient")
+
+ }
+}
diff --git a/imports/shared/controls/Icon.qml b/imports/shared/controls/Icon.qml
new file mode 100644
index 0000000..7adb677
--- /dev/null
+++ b/imports/shared/controls/Icon.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import utils 1.0
+
+UIElement {
+ id: root
+ hspan: 2
+ vspan: 2
+
+ property string source
+ property bool fit: false
+
+ Image {
+ id: defaultIcon
+ width: root.fit ? root.width : undefined
+ height: root.fit ? root.height : undefined
+ anchors.centerIn: parent
+ source: root.source ? root.source : ""
+ opacity: root.enabled ? 1.0 : 0.5
+ asynchronous: true
+ fillMode: root.fit ? Image.PreserveAspectFit : Image.Pad
+ Behavior on opacity { NumberAnimation { duration: 250 } }
+ }
+}
diff --git a/imports/shared/controls/Label.qml b/imports/shared/controls/Label.qml
new file mode 100644
index 0000000..4b1ec7f
--- /dev/null
+++ b/imports/shared/controls/Label.qml
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import utils 1.0
+
+Text {
+ id: textElement
+
+ verticalAlignment: Text.AlignVCenter
+ font.family: Style.fontFamily
+ font.weight: Style.fontWeight
+ color: Style.colorWhite
+ clip: Style.debugMode
+ font.pixelSize: Style.fontSizeS
+}
diff --git a/imports/shared/controls/LaunchItemBackground.qml b/imports/shared/controls/LaunchItemBackground.qml
new file mode 100644
index 0000000..e6cf537
--- /dev/null
+++ b/imports/shared/controls/LaunchItemBackground.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt multiscreen demo application.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import QtApplicationManager 1.0
+import utils 1.0
+
+Item {
+ property alias text: title.text
+ property string applicationName
+ scale: area.pressed?0.85:1.0
+
+ Behavior on scale {
+ NumberAnimation {}
+ }
+
+ Image {
+ source: Style.symbol("RectangleGradient256x512")
+ anchors.fill: parent
+ }
+
+ Label {
+ id: title
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: Style.paddingXXL
+ }
+
+ MouseArea {
+ id: area
+ anchors.fill: parent
+ onClicked: {
+ ApplicationManager.startApplication(applicationName)
+ }
+ }
+}
diff --git a/imports/shared/controls/Slider.qml b/imports/shared/controls/Slider.qml
new file mode 100644
index 0000000..9614290
--- /dev/null
+++ b/imports/shared/controls/Slider.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+import utils 1.0
+
+UIElement {
+ id: root;
+ hspan: 7
+ vspan: 2
+ property real value // value is read/write.
+ property real minimum: 0
+ property real maximum: 1
+ property int length: width - handle.width
+ property int timeLineHeight: 15
+ property real activeValue
+
+ function valueToString() {
+ return activeValue.toFixed(2)
+ }
+
+ Rectangle {
+ id: background
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ height: timeLineHeight
+ radius: 4
+ border.color: Qt.lighter(color, 1.1)
+ color: "#999"
+ opacity: 0.25
+ }
+
+ Rectangle {
+ id: labelRect
+ width: label.width
+ height: label.height + 4
+ radius: 4
+ smooth: true
+ color: "#000"
+ border.color: Qt.lighter(color, 1.1)
+ anchors.bottom: handle.top
+ anchors.bottomMargin: 4
+ x: Math.max(Math.min(handle.x + (handle.width - width )/2, root.width - width),0)
+ visible: area.pressed
+ opacity: 0.75
+
+ Text{
+ id: label
+ color: Style.colorWhite
+ font.family: Style.fontFamily
+ font.pixelSize: Style.fontSizeS
+ text: root.valueToString()
+ width: font.pointSize * 3.5
+ anchors.horizontalCenter: labelRect.horizontalCenter
+ horizontalAlignment: Text.AlignHCenter
+ anchors.baseline: parent.bottom
+ anchors.baselineOffset: -6
+ }
+ }
+
+ Rectangle {
+ id: handle;
+ smooth: true
+ width: handle.x ? 10 : 0
+ y: (root.height - height)/2;
+ x: (root.value - root.minimum) * root.length / (root.maximum - root.minimum)
+
+ height: timeLineHeight; radius: 4
+ border.color: Qt.lighter(color, 1.1)
+ color: Style.colorPink
+
+ MouseArea {
+ id: area
+ hoverEnabled: false
+ anchors.fill: parent; drag.target: parent
+ drag.axis: Drag.XAxis; drag.minimumX: 0; drag.maximumX: root.length
+ onPositionChanged: {
+ root.activeValue = root.minimum + (root.maximum - root.minimum) * handle.x / root.length
+ }
+ }
+ }
+ Rectangle {
+ id: handleTail
+ y: handle.y;
+ radius: handle.radius; color: handle.color
+ anchors.left: background.left
+ anchors.right: handle.right
+ width: handle.x; height: handle.height
+ }
+}
diff --git a/imports/shared/controls/SwipeView.qml b/imports/shared/controls/SwipeView.qml
new file mode 100644
index 0000000..cad2771
--- /dev/null
+++ b/imports/shared/controls/SwipeView.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+import utils 1.0
+
+UIElement {
+ id: root
+
+ property alias delegate: pathView.delegate
+ property alias items: pathView.model
+ property alias currentViewIndex: pathView.currentIndex
+
+ property int itemWidth
+
+ PathView {
+ id: pathView
+
+ property int padding: (width-root.itemWidth)/2
+
+ anchors.fill: parent
+ clip: true
+
+ snapMode: PathView.SnapOneItem
+
+ pathItemCount: 3
+
+ preferredHighlightBegin: 0.5
+ preferredHighlightEnd: 0.5
+
+ path: Path {
+ startX: -root.itemWidth+pathView.padding
+ startY: pathView.height/2
+ PathAttribute { name: "scale"; value: 0.5 }
+ PathAttribute { name: "angle"; value: -100 }
+ PathAttribute { name: "z"; value: 0 }
+ PathAttribute { name: "yTranslate"; value: Style.vspan(4) }
+
+ PathLine { x: pathView.width/2; y: pathView.height/2 }
+ PathAttribute { name: "scale"; value: 1 }
+ PathAttribute { name: "angle"; value: 0 }
+ PathAttribute { name: "z"; value: 1 }
+ PathAttribute { name: "yTranslate"; value: 0 }
+
+ PathLine { x: pathView.width + root.itemWidth-pathView.padding; y: pathView.height/2 }
+ PathAttribute { name: "scale"; value: 0.5 }
+ PathAttribute { name: "angle"; value: 100 }
+ PathAttribute { name: "z"; value: 0 }
+ PathAttribute { name: "yTranslate"; value: Style.vspan(4) }
+ }
+ }
+}
diff --git a/imports/shared/controls/Symbol.qml b/imports/shared/controls/Symbol.qml
new file mode 100644
index 0000000..ed1717a
--- /dev/null
+++ b/imports/shared/controls/Symbol.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import utils 1.0
+
+Item {
+ id: root
+ implicitHeight: image.height
+ implicitWidth: image.width
+
+ signal activeSymbolChanged()
+
+ property string name
+ property bool active
+ property int size: Style.defaultSymbolSize
+ property alias rotate: image.rotation
+ Image {
+ id: image
+ anchors.centerIn: parent
+ source: root.name ? Style.symbol(root.name, root.active) : ""
+ asynchronous: true
+ }
+}
diff --git a/imports/shared/controls/Tool.qml b/imports/shared/controls/Tool.qml
new file mode 100644
index 0000000..d5b6af2
--- /dev/null
+++ b/imports/shared/controls/Tool.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import controls 1.0
+import utils 1.0
+
+UIElement {
+ id: root
+ hspan: 1
+ vspan: 2
+ property alias name: icon.name
+ property alias size: icon.size
+ property bool active
+ scale: area.pressed ? 1.1 : 1.0
+ Behavior on scale { NumberAnimation { duration: 25 } }
+
+ signal clicked()
+
+ function toggle() {
+ active = !active
+ }
+
+ Symbol {
+ id: icon
+ anchors.fill: parent
+ active: area.pressed || root.active
+ opacity: 0.75
+ }
+
+ MouseArea {
+ id: area
+ anchors.fill: parent
+ onClicked: root.clicked()
+ }
+}
diff --git a/imports/shared/controls/qmldir b/imports/shared/controls/qmldir
new file mode 100644
index 0000000..3a052d2
--- /dev/null
+++ b/imports/shared/controls/qmldir
@@ -0,0 +1,14 @@
+Icon 1.0 Icon.qml
+Label 1.0 Label.qml
+Button_neptune 1.0 Button_neptune.qml
+DisplayBackground 1.0 DisplayBackground.qml
+TabView 1.0 TabView.qml
+Tool 1.0 Tool.qml
+TextTool 1.0 TextTool.qml
+Slider 1.0 Slider.qml
+Symbol 1.0 Symbol.qml
+AppStackView 1.0 AppStackView.qml
+SwipeView 1.0 SwipeView.qml
+LetterPicker 1.0 LetterPicker.qml
+Title 1.0 Title.qml
+LaunchItemBackground 1.0 LaunchItemBackground.qml
diff --git a/imports/shared/service/climate/ClimateService.qml b/imports/shared/service/climate/ClimateService.qml
new file mode 100644
index 0000000..ffdf71b
--- /dev/null
+++ b/imports/shared/service/climate/ClimateService.qml
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.0
+import QtIvi.VehicleFunctions 1.0
+import service.settings 1.0
+
+QtObject {
+ id: root
+
+ property ClimateControl climateControl: ClimateControl {
+ discoveryMode: ClimateControl.AutoDiscovery
+ }
+
+ property QtObject leftSeat: QtObject {
+ property real minValue: calculateUnitValue(16)
+ property real maxValue: calculateUnitValue(28)
+ property real stepValue: calculateUnitValue(0.5)
+ property real value: calculateUnitValue(climateControl.zoneAt.FrontLeft.targetTemperature.value)
+ property bool heat: climateControl.zoneAt.FrontLeft.seatHeater
+ }
+
+ property QtObject rightSeat: QtObject {
+ property real minValue: calculateUnitValue(16)
+ property real maxValue: calculateUnitValue(28)
+ property real stepValue: calculateUnitValue(0.5)
+ property real value: calculateUnitValue(climateControl.zoneAt.FrontRight.targetTemperature.value)
+
+ property bool heat: climateControl.zoneAt.FrontRight.seatHeater
+
+ onValueChanged: climateControl.zoneAt.FrontRight.targetTemperature.value = value
+ onHeatChanged: climateControl.zoneAt.FrontRight.seatHeater.value = heat
+ }
+
+ property QtObject frontHeat: QtObject {
+ property string symbol: "front"
+ property bool enabled: true
+ }
+
+ property QtObject rearHeat: QtObject {
+ property string symbol: "rear"
+ property bool enabled: true
+ }
+
+ property QtObject airCondition: QtObject {
+ property string symbol: "ac"
+ property bool enabled: climateControl.airConditioning.value
+
+ onEnabledChanged: {
+ climateControl.airConditioning.value = enabled;
+ enabled = Qt.binding(function() { return climateControl.airConditioning.value; });
+ }
+ }
+
+ property QtObject airflow: QtObject {
+ property int windshield: ClimateControl.Windshield
+ property int dashboard: ClimateControl.Dashboard
+ property int floor: ClimateControl.Floor
+ property int value: climateControl.airflowDirections.value
+ property var availableValues: climateControl.airflowDirections.availableValues
+ }
+
+ property QtObject airQuality: QtObject {
+ property string symbol: "air_quality"
+ property bool enabled: climateControl.recirculationMode.value == ClimateControl.RecirculationOn
+
+ onEnabledChanged: {
+ climateControl.recirculationMode.value = enabled ? ClimateControl.RecirculationOn : ClimateControl.RecirculationOff;
+ enabled = Qt.binding(function() { return climateControl.recirculationMode.value == ClimateControl.RecirculationOn });
+ }
+ }
+
+ property QtObject eco: QtObject {
+ property string symbol: "eco"
+ property bool enabled: false
+ }
+
+ property QtObject steeringWheelHeat: QtObject {
+ property string symbol: "stearing_wheel"
+ property bool enabled: climateControl.steeringWheelHeater.value >= 5
+
+ onEnabledChanged: {
+ climateControl.steeringWheelHeater.value = enabled ? 10 : 0;
+ enabled = Qt.binding(function() { return climateControl.steeringWheelHeater.value >= 5 });
+ }
+ }
+
+ property var climateOptions: [frontHeat, rearHeat, airCondition, airQuality, eco, steeringWheelHeat]
+
+ property int outsideTemp: calculateUnitValue(15)
+ property string outsideTempText: qsTr("%1" + tempSuffix).arg(outsideTemp)
+ property int ventilation: climateControl.fanSpeedLevel.value
+ property string tempSuffix: SettingsService.metric ? "°C" : "°F"
+ property int ventilationLevels: climateControl.fanSpeedLevel.maximumValue // 6 + off (0)
+ onVentilationChanged: climateControl.fanSpeedLevel.value = ventilation
+
+ property QtObject stateMachine: ClimateStateMachine {
+ climateControl: root.climateControl
+ doorsOpen: eco.enabled // TODO use QtIVI doors/window state for this eventually
+ }
+
+ function calculateUnitValue(value) {
+ // Defualt value is the celsius
+ return (SettingsService.unitSystem === "metric") ? value : (Math.round(value * 1.8 + 32))
+ }
+}
diff --git a/imports/shared/service/climate/ClimateStateMachine.qml b/imports/shared/service/climate/ClimateStateMachine.qml
new file mode 100644
index 0000000..596be08
--- /dev/null
+++ b/imports/shared/service/climate/ClimateStateMachine.qml
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQml.StateMachine 1.0 as DSM
+import QtIvi.VehicleFunctions 1.0
+
+QtObject {
+ id: root
+ property ClimateControl climateControl
+ property bool doorsOpen: false
+
+ property QtObject stateMachine: DSM.StateMachine {
+ id: climateStateMachine
+ running: true
+ initialState: runningState
+
+ DSM.State {
+ childMode: DSM.State.ParallelStates
+ id: runningState
+
+ DSM.State {
+ id: suspendable
+ initialState: doorsClosedState
+
+ DSM.State {
+ id: doorsClosedState
+ childMode: DSM.State.ParallelStates
+
+ DSM.State {
+ id: airConditionState
+ initialState: climateControl.airConditioning.value ? airConditionOn : airConditionOff
+
+ DSM.State {
+ id: airConditionOff
+ onEntered: climateControl.airConditioning.value = false
+ DSM.SignalTransition {
+ targetState: airConditionOn
+ signal: climateControl.airConditioning.valueChanged
+ guard: climateControl.airConditioning.value
+ }
+ }
+
+ DSM.State {
+ id: airConditionOn
+ onEntered: {
+ climateControl.airConditioning.value = true
+ steeringWheelHeat.enabled = false
+ }
+ DSM.SignalTransition {
+ targetState: airConditionOff
+ signal: climateControl.airConditioning.valueChanged
+ guard: !climateControl.airConditioning.value
+ }
+ }
+ } // airConditionState
+
+ DSM.State {
+ id: airRecirculationState
+ initialState: climateControl.recirculation.value ? airRecirculationOn : airRecirculationOff
+
+ DSM.State {
+ id: airRecirculationOff
+ onEntered: climateControl.recirculationMode.value = ClimateControl.RecirculationOff
+ DSM.SignalTransition {
+ targetState: airRecirculationOn
+ signal: climateControl.recirculationMode.valueChanged
+ guard: climateControl.recirculationMode.value == ClimateControl.RecirculationOn
+ }
+ }
+
+ DSM.State {
+ id: airRecirculationOn
+ onEntered: {
+ climateControl.recirculationMode.value = ClimateControl.RecirculationOn
+ }
+ DSM.SignalTransition {
+ targetState: airRecirculationOff
+ signal: climateControl.recirculationMode.valueChanged
+ guard: climateControl.recirculationMode.value == ClimateControl.RecirculationOff
+ }
+ }
+ } // airRecirculationState
+
+ DSM.HistoryState {
+ id: historyState
+ defaultState: doorsClosedState
+ historyType: DSM.HistoryState.DeepHistory
+ }
+
+ DSM.SignalTransition {
+ targetState: suspended
+ signal: doorsOpenChanged
+ guard: doorsOpen
+ }
+ } // door closed state
+
+ DSM.State {
+ id: suspended
+ onEntered: {
+ climateControl.airConditioning.value = false
+ climateControl.recirculationMode.value = ClimateControl.RecirculationOff
+ }
+ DSM.SignalTransition {
+ targetState: historyState
+ signal: doorsOpenChanged
+ guard: !doorsOpen
+ }
+ }
+
+ } // suspendable state
+
+ DSM.State {
+ id: steeringWheelHeatState
+ initialState: (climateControl.steeringWheelHeater.value >= 5) ? steeringWheelHeatOn : steeringWheelHeatOff
+
+ DSM.State {
+ id: steeringWheelHeatOff
+ onEntered: climateControl.steeringWheelHeater.value = 0
+ DSM.SignalTransition {
+ targetState: steeringWheelHeatOn
+ signal: climateControl.steeringWheelHeater.valueChanged
+ guard: climateControl.steeringWheelHeater.value >= 5
+ }
+ }
+
+ DSM.State {
+ id: steeringWheelHeatOn
+ onEntered: {
+ climateControl.steeringWheelHeater.value = 10
+ climateControl.airConditioning.value = false
+ }
+ DSM.SignalTransition {
+ targetState: steeringWheelHeatOff
+ signal: climateControl.steeringWheelHeater.valueChanged
+ guard: climateControl.steeringWheelHeater.value < 5
+ }
+ }
+ }
+ } // running state
+ }
+}
diff --git a/imports/shared/service/climate/qmldir b/imports/shared/service/climate/qmldir
new file mode 100644
index 0000000..322284f
--- /dev/null
+++ b/imports/shared/service/climate/qmldir
@@ -0,0 +1 @@
+singleton ClimateService 1.0 ClimateService.qml
diff --git a/imports/shared/service/movie/MovieService.qml b/imports/shared/service/movie/MovieService.qml
new file mode 100644
index 0000000..0e9655b
--- /dev/null
+++ b/imports/shared/service/movie/MovieService.qml
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+pragma Singleton
+
+import QtQuick 2.0
+import "." 1.0
+
+QtObject {
+ id: root
+ property var movieProvider
+ property int currentIndex: 0
+ property int trackCount
+ property var currentTrack
+
+
+ function nextTrack() {
+ if (movieProvider)
+ movieProvider.next()
+ }
+
+ function previousTrack() {
+ if (movieProvider)
+ movieProvider.previous()
+ }
+
+ function sourcePath(source) {
+ return movieProvider ? movieProvider.sourcePath(source) : ""
+ }
+
+
+ function coverPath(cover) {
+ return movieProvider ? movieProvider.coverPath(cover) : ""
+ }
+
+ function selectRandomTracks() {
+ if (movieProvider)
+ movieProvider.selectRandom()
+ }
+}
diff --git a/imports/shared/service/movie/qmldir b/imports/shared/service/movie/qmldir
new file mode 100644
index 0000000..764d674
--- /dev/null
+++ b/imports/shared/service/movie/qmldir
@@ -0,0 +1 @@
+singleton MovieService 1.0 MovieService.qml
diff --git a/imports/shared/service/music/MusicService.qml b/imports/shared/service/music/MusicService.qml
new file mode 100644
index 0000000..22e858b
--- /dev/null
+++ b/imports/shared/service/music/MusicService.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.0
+import QtMultimedia 5.0
+import "." 1.0
+
+QtObject {
+ id: root
+
+ property string defaultMusicApp: "com.pelagicore.media"
+ property var musicProvider
+ property Audio player: Audio {
+ id: player
+ source: currentTrack ? root.url : ""
+ onVolumeChanged: {
+ print('volume: ' + volume)
+ }
+ onStatusChanged: {
+ if (status == Audio.EndOfMedia)
+ nextTrack()
+ }
+ }
+
+ property alias volume: player.volume
+
+ property int currentIndex
+ property int trackCount
+ property var currentTrack
+ property string coverPath
+ property bool playing: player.playbackState === Audio.PlayingState
+ property alias duration: player.duration
+ property alias position: player.position
+ property string currentTime: Qt.formatTime(new Date(position), 'mm:ss')
+ property string durationTime: Qt.formatTime(new Date(duration), 'mm:ss')
+ property int remaining: player.duration - player.position
+ property string remainingTime: Qt.formatTime(new Date(remaining), 'mm:ss')
+ property string url
+
+ function musicPlay() {
+ player.source = Qt.binding(function() { return currentTrack ? root.url : ""})
+ play()
+ }
+
+ function play() {
+ print('MusicService.play: ' + player.source)
+ player.autoPlay = true
+ player.play()
+ }
+
+ function pause() {
+ print('MusicService.pause: ' + player.source)
+ player.autoPlay = false
+ player.pause()
+ }
+
+ function togglePlay() {
+ if (playing) {
+ pause()
+ } else {
+ play()
+ }
+ }
+
+ function nextTrack() {
+ if (root.musicProvider)
+ root.musicProvider.next()
+ }
+
+ function previousTrack() {
+ if (root.musicProvider)
+ root.musicProvider.previous()
+ }
+
+ function selectAllAlbums() {
+ provider.query = 'select distinct album, cover, artist from music'
+ }
+
+ function seek(value) {
+ player.seek(value)
+ }
+
+ Component.onDestruction: {
+ // required to avoid crashing qmllive
+ player.autoLoad = false
+ player.autoPlay = false
+ player.stop()
+ player.source = ''
+ }
+}
diff --git a/imports/shared/service/music/qmldir b/imports/shared/service/music/qmldir
new file mode 100644
index 0000000..3ca99e6
--- /dev/null
+++ b/imports/shared/service/music/qmldir
@@ -0,0 +1 @@
+singleton MusicService 1.0 MusicService.qml
diff --git a/imports/shared/service/settings/SettingsService.qml b/imports/shared/service/settings/SettingsService.qml
new file mode 100644
index 0000000..10577bc
--- /dev/null
+++ b/imports/shared/service/settings/SettingsService.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.1
+
+QtObject {
+ id: root
+
+ property bool clusterVisible: true
+ property string unitSystem: "metric" // "metric" or "imp_us"
+ property bool metric: unitSystem === "metric"
+
+ property ListModel entries: ListModel {
+ ListElement { title: "USER PROFILE"; icon: "profile"; checked: true; hasChildren: true }
+ ListElement { title: "SERVICE & SUPPORT"; icon: "service"; checked: false; hasChildren: false }
+ ListElement { title: "TRAFFIC INFORMATION"; icon: "warning"; checked: true; hasChildren: true }
+ ListElement { title: "TOLL & CONGESTION FEES"; icon: "toll"; checked: false; hasChildren: true }
+ ListElement { title: "METRIC SYSTEM"; icon: "fees"; checked: true; hasChildren: false }
+ ListElement { title: "APP UPDATES"; icon: "updates"; checked: true; hasChildren: true }
+ ListElement { title: "INSURANCE FEATURES"; icon: "insurance"; checked: true; hasChildren: true }
+ }
+
+ property var carSettings: [
+ { section: "Units", option: clockOption },
+ { section: "Units", option: speedOption },
+ { section: "Communication", option: bluetoothOption }
+ ]
+
+ property var clockOption: QtObject {
+ property string format: active === 0 ? "hh:mm" : "h:mm AP"
+ property var options: ['24H', 'AM/PM']
+ property string name: "Time"
+ property int active: 0
+
+ function setActive(index) { active = index }
+ }
+
+ property var speedOption: QtObject {
+ property var options: ['KMH', 'MPH']
+ property string name: "Speed"
+ property int active: 0
+
+ function setActive(index) { active = index }
+ }
+
+ property var bluetoothOption: QtObject {
+
+ property string name: "Bluetooth"
+ property bool active: false
+
+ function setActive(value) { active = value }
+ }
+
+ property ListModel functions: ListModel {
+ ListElement {
+ description: "Hill descent control"
+ icon: "hill_descent_control"
+ active: true
+ }
+ ListElement {
+ description: "Intelligent speed adaptation"
+ icon: "intelligent_speed_adaptation"
+ active: false
+ }
+ ListElement {
+ description: "Automatic beam switching"
+ icon: "automatic_beam_switching"
+ active: true
+ }
+ ListElement {
+ description: "Collision avoidance"
+ icon: "collision_avoidance"
+ active: false
+ }
+ ListElement {
+ description: "Lane keeping assist"
+ icon: "lane_keeping_assist"
+ active: false
+ }
+ ListElement {
+ description: "Traffic jam assist"
+ icon: "traffic_jam_assist"
+ active: false
+ }
+ ListElement {
+ description: "Driver drowsyness alert"
+ icon: "driver_drownsyness_alert"
+ active: true
+ }
+ ListElement {
+ description: "Park assist"
+ icon: "park_assist"
+ active: false
+ }
+ }
+}
diff --git a/imports/shared/service/settings/qmldir b/imports/shared/service/settings/qmldir
new file mode 100644
index 0000000..950972f
--- /dev/null
+++ b/imports/shared/service/settings/qmldir
@@ -0,0 +1 @@
+singleton SettingsService 1.0 SettingsService.qml
diff --git a/imports/shared/service/statusbar/StatusBarService.qml b/imports/shared/service/statusbar/StatusBarService.qml
new file mode 100644
index 0000000..e14bc30
--- /dev/null
+++ b/imports/shared/service/statusbar/StatusBarService.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.0
+import service.settings 1.0
+
+Item {
+ id: root
+
+ property string clusterTitle: ""
+ property int pageIndicatorSize: 3
+ property int currentPage: 0
+
+ property var indicators: [
+ { name: "4g-signal-strength", active: true },
+ { name: "bluetooth", active: SettingsService.bluetoothOption.active },
+ { name: "wifi-signal-strength", active: true }
+ ]
+
+ property var currentDate: new Date();
+
+ Timer {
+ interval: 1000
+ repeat: true
+ running: true
+ onTriggered: {
+ currentDate = new Date()
+ }
+ }
+
+ visible: false
+}
diff --git a/imports/shared/service/statusbar/qmldir b/imports/shared/service/statusbar/qmldir
new file mode 100644
index 0000000..129171d
--- /dev/null
+++ b/imports/shared/service/statusbar/qmldir
@@ -0,0 +1 @@
+singleton StatusBarService 1.0 StatusBarService.qml
diff --git a/imports/shared/service/valuesource/ValueSource.qml b/imports/shared/service/valuesource/ValueSource.qml
new file mode 100644
index 0000000..a534903
--- /dev/null
+++ b/imports/shared/service/valuesource/ValueSource.qml
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.6
+import com.qtcompany.clusterdemodata 1.0
+
+Item {
+ id: valueSource
+ property real kph: 0
+ property real consumeKW: 0
+ property real maxConsumeKWValue: 90
+ property real maxChargeKWValue: 40
+ property real chargeKW: 0
+ property real maxRange: 600
+ property real range: (batteryLevel / 100) * maxRange
+
+ property string destination: "Ernst-Reuter-Platz"
+ property string currentLocation: "Kurt-Schumacher-Damm"
+
+ property var consumption: [300, 600, 700, 800, 900, 700, 600, 300, 50, 50, -100, 50, -100, -150,
+ -200, 50, 150, 200, 300, 200, 300, 200, 500, 50, -100, -100, -150, -80, 50, 300, 600, 700, 800,
+ 600, 700, 300, 50, 50]
+
+ property var turnSignal
+ property var currentDate: new Date()
+ //property string date: currentDate.toLocaleDateString(Qt.locale("fi_FI"), "ddd d. MMM")
+ //property string time: currentDate.toLocaleTimeString(Qt.locale("fi_FI"), "hh:mm")
+ property string date: currentDate.toLocaleDateString(Qt.locale("en_GB"))
+ property string time: currentDate.toLocaleTimeString(Qt.locale("en_GB"), "hh:mm")
+
+ ClusterData {
+ id: clusterDataSource
+
+ onVehicleSpeedChanged: {
+ kph = vehicleSpeed
+ }
+ property int notLeft: ~Qt.LeftArrow
+ property int notRight: ~Qt.RightArrow
+ onLeftTurnLightChanged: leftTurnLight ? turnSignal |= Qt.LeftArrow
+ : turnSignal &= notLeft
+ onRightTurnLightChanged: rightTurnLight ? turnSignal |= Qt.RightArrow
+ : turnSignal &= notRight
+ }
+
+ property real latitude: clusterDataSource.latitude
+ property real longitude: clusterDataSource.longitude
+ property real direction: clusterDataSource.direction
+ property bool lowBeam: automaticDemoMode//clusterDataSource.headLight
+ property int carId: clusterDataSource.carId
+ property bool lightFailure: clusterDataSource.lightFailure
+ property bool flatTire: clusterDataSource.flatTire
+
+ property bool frontLeftOpen: clusterDataSource.zoneAt.frontLeft.doorOpen
+ property bool frontRightOpen: clusterDataSource.zoneAt.frontRight.doorOpen
+ property bool rearLeftDoorOpen: clusterDataSource.zoneAt.rearLeft.doorOpen
+ property bool rearRighDoorOpen: clusterDataSource.zoneAt.rearRight.doorOpen
+ property bool hoodOpen: clusterDataSource.zoneAt.hood.doorOpen
+ property bool trunkOpen: clusterDataSource.zoneAt.trunk.doorOpen
+
+ property double batteryLevel: clusterDataSource.batteryPotential
+ property double fuelLevel: clusterDataSource.gasLevel
+ property int gear: clusterDataSource.gear
+ property bool parkingBrake: clusterDataSource.brake
+ // TODO: These two are hacks. View change messages might not come through CAN.
+ property bool viewChange: clusterDataSource.oilTemp
+ property bool rightViewChange: clusterDataSource.oilPressure
+
+ //
+ // ENABLE FOR FULLY AUTOMATIC DEMO MODE (in case there is no CanController)
+ //
+ property bool automaticDemoMode: true
+ property bool startAnimations: false
+
+ onAutomaticDemoModeChanged: {
+ if (startAnimations) {
+ kph = 0
+ if (automaticDemoMode) {
+ animation.start()
+ } else {
+ gear = 1
+ parkingBrake = false
+ animation.stop()
+ }
+ }
+ }
+
+ onStartAnimationsChanged: {
+ if (startAnimations)
+ animation.start()
+ }
+
+ //
+ // Speed animations for automatic demo mode
+ //
+ Timer {
+ running: startAnimations && automaticDemoMode
+ property bool turnLeft: true
+ repeat: true
+ interval: 7500
+ onTriggered: {
+ turnLeft = !turnLeft
+ if (turnLeft)
+ turnSignal = Qt.LeftArrow
+ else
+ turnSignal = Qt.RightArrow
+ stopSignaling.restart()
+ }
+ }
+
+ Timer {
+ id: stopSignaling
+ running: false
+ interval: 2750
+ onTriggered: turnSignal = Qt.NoArrow
+ }
+
+ Behavior on fuelLevel {
+ enabled: automaticDemoMode
+ PropertyAnimation {
+ duration: 18000
+ }
+ }
+
+ Behavior on batteryLevel {
+ enabled: automaticDemoMode
+ PropertyAnimation {
+ duration: 18000
+ }
+ }
+
+ onFuelLevelChanged: {
+ if (automaticDemoMode && fuelLevel <= 5)
+ fuelLevel = 100
+ }
+
+ onBatteryLevelChanged: {
+ if (automaticDemoMode && batteryLevel <= 5)
+ batteryLevel = 100
+ }
+
+ SequentialAnimation {
+ id: animation
+ running: false
+ loops: Animation.Infinite
+
+ ScriptAction {
+ script: {
+ gear = 0
+ parkingBrake = true
+ }
+ }
+ PauseAnimation { duration: 2000 }
+ ScriptAction {
+ script: {
+ parkingBrake = false
+ gear = 1
+ fuelLevel -= 10.
+ batteryLevel -= 10.
+ }
+ }
+ PropertyAnimation {
+ target: valueSource
+ property: "kph"
+ from: 0
+ to: 150
+ duration: 10000
+ }
+ PropertyAnimation {
+ target: valueSource
+ property: "kph"
+ from: 150
+ to: 120
+ duration: 500
+ }
+ PropertyAnimation {
+ target: valueSource
+ property: "kph"
+ from: 120
+ to: 200
+ duration: 1500
+ }
+ PropertyAnimation {
+ target: valueSource
+ property: "kph"
+ from: 200
+ to: 0
+ duration: 6000
+ }
+ }
+
+ // In normal Car UI mode only speed is animated based on gps data
+ // In automatic demo mode rpm, turbo, consumption and engine temperature are based on speed
+ //property int rpm: automaticDemoMode ? kph * 40 : kph * 150
+ //property double engineTemperature: automaticDemoMode ? kph * .25 + 60. : kph * .5 + 50.
+ // New route is faster, we can use the same values for both modes
+ property int rpm: kph * 40
+ property double engineTemperature: kph * .22 + 60.
+
+ property int totalDistance: 42300
+ property int kmSinceCharge: 8
+ property int avRangePerCharge: 425
+ property int energyPerKm: 324
+
+ property real totalDistanceSince: 0.
+
+ property string gearString: {
+ var g
+ if (gear === 0 || gear < -1)
+ return "N"
+ else if (gear === -1)
+ return "R"
+ else if (carId === 1) //sports car
+ return gear.toString()
+ else
+ return "D"
+ }
+
+ Timer {
+ id: timeTimer
+ interval: 15000
+ repeat: true
+ running: true
+ onTriggered: {
+ currentDate = new Date()
+ //date = currentDate.toLocaleDateString(Qt.locale("fi_FI"), "ddd d. MMM")
+ //time = currentDate.toLocaleTimeString(Qt.locale("fi_FI"), "hh:mm")
+ date = currentDate.toLocaleDateString(Qt.locale("en_GB"))
+ time = currentDate.toLocaleTimeString(Qt.locale("en_GB"), "hh:mm")
+ // Approximate total distance based on current speed
+ totalDistanceSince += kph / 240. // = km / 15 min
+ if (totalDistanceSince > 1.) {
+ var totalInt = Math.floor(totalDistanceSince)
+ totalDistance += totalInt
+ kmSinceCharge += totalInt
+ totalDistanceSince -= totalInt
+ }
+ }
+ }
+
+ Behavior on kph {
+ enabled: !automaticDemoMode
+ PropertyAnimation { duration: 2000 }
+ }
+}
diff --git a/imports/shared/service/valuesource/qmldir b/imports/shared/service/valuesource/qmldir
new file mode 100644
index 0000000..844c635
--- /dev/null
+++ b/imports/shared/service/valuesource/qmldir
@@ -0,0 +1 @@
+singleton ValueSource 1.0 ValueSource.qml
diff --git a/imports/shared/utils/AppUIScreen.qml b/imports/shared/utils/AppUIScreen.qml
new file mode 100644
index 0000000..fc80c06
--- /dev/null
+++ b/imports/shared/utils/AppUIScreen.qml
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.1
+
+import QtApplicationManager 1.0
+import controls 1.0
+import utils 1.0
+
+ApplicationManagerWindow {
+ id: pelagicoreWindow
+ width: Style.cellWidth * 24
+ height: Style.cellHeight * 24
+
+ default property alias content: content.children
+ property var clusterComponent
+ property alias cluster: clusterContainer.children
+ property alias passenger: passengerContainer.children
+
+ signal clusterKeyPressed(int key)
+ signal raiseApp()
+
+ onWindowPropertyChanged: {
+ //print(":::AppUIScreen::: Window property changed", name, value)
+ if (name === "visibility" && value === true) {
+ pelagicoreWindow.raiseApp()
+ }
+ }
+
+ function back() {
+ pelagicoreWindow.setWindowProperty("visibility", false)
+ }
+
+ DisplayBackground {
+ anchors.fill: parent
+ }
+
+ ApplicationManagerWindow {
+ id: clusterSurface
+ width: typeof parent !== 'undefined' ? parent.width : Style.cellWidth * 24
+ height: typeof parent !== 'undefined' ? parent.height : Style.cellHeight * 24
+ color: "transparent"
+ visible: clusterContainer.children.length > 0 && Style.withCluster
+ Item {
+ id: clusterContainer
+ anchors.fill: parent
+ }
+
+ Component.onCompleted: {
+ clusterSurface.setWindowProperty("windowType", "clusterWidget")
+ }
+
+ onWindowPropertyChanged: {
+ //print(":::AppUIScreen::: window property changed", name, value, Qt.Key_Up)
+ pelagicoreWindow.clusterKeyPressed(value)
+ if (name === "visibility") {
+ clusterSurface.visible = value
+ }
+ }
+ }
+
+ ApplicationManagerWindow {
+ id: passengerSurface
+ width: typeof parent !== 'undefined' ? parent.width : Style.cellWidth * 24
+ height: typeof parent !== 'undefined' ? parent.height : Style.cellHeight * 24
+ visible: passengerContainer.children.length > 0
+ color: "transparent"
+
+ Item {
+ id: passengerContainer
+ anchors.fill: parent
+ }
+ Component.onCompleted: {
+ passengerSurface.setWindowProperty("windowType", "passengerWidget")
+ }
+ }
+
+ Item {
+ id: content
+ anchors.fill: parent
+ }
+}
diff --git a/imports/shared/utils/AutoConfig.qml b/imports/shared/utils/AutoConfig.qml
new file mode 100644
index 0000000..fb4c07d
--- /dev/null
+++ b/imports/shared/utils/AutoConfig.qml
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Window 2.2
+import com.pelagicore.ScreenManager 1.0
+
+QtObject {
+ property bool withCluster: false
+ property int cellWidth: 53 // 1280/24
+ property int cellHeight: 33 // 800/24
+ property var fontWeight: Font.Light
+ property int fontSizeXXS: 12
+ property int fontSizeXS: 18
+ property int fontSizeS: 24
+ property int fontSizeM: 28
+ property int fontSizeL: 38
+ property int fontSizeXL: 60
+ property int fontSizeXXL: 80
+
+ property int defaultSymbolSize: symbolSizeS
+ property int defaultGfxSize: 1
+ property int symbolSizeXS: 32
+ property int symbolSizeS: 48
+ property int symbolSizeM: 72
+ property int symbolSizeL: 96
+ property int symbolSizeXL: 114
+ property int symbolSizeXXL: 192
+
+ property string displayBackground: "background_1920x1080"
+
+
+ property int screenWidth: Screen.width
+ property int screenHeight: Math.min(screenWidth * 0.62, Screen.height)
+ property int clusterWidth: 1920
+ property int clusterHeight: 720
+
+ onScreenWidthChanged: cellWidth = Math.floor(screenWidth/24)
+ onScreenHeightChanged: cellHeight = Math.floor(screenHeight/24)
+
+ Component.onCompleted: {
+ var scalFactor = (screenWidth/1280);
+
+ print("resolution: " + screenWidth + "x" + screenHeight)
+ print("scalFactor: ", scalFactor)
+
+ cellWidth = Math.floor(screenWidth/24)
+ cellHeight = Math.floor(screenHeight/24)
+
+ var symbolSize = symbolSizeS
+ var gfxSize = 1
+ if (scalFactor >= 6) {
+ symbolSize = symbolSizeXL
+ gfxSize = 4
+ } else if (scalFactor >= 2) {
+ symbolSize = symbolSizeL
+ gfxSize = 3
+ } else if (scalFactor >= 1.5) {
+ symbolSize = symbolSizeM
+ gfxSize = 2
+ }
+
+ defaultSymbolSize = symbolSize
+ defaultGfxSize = 4
+
+
+ fontSizeXXS = scalFactor * 14
+
+ fontSizeXS = scalFactor * 16
+
+ fontSizeS = scalFactor * 18
+
+ fontSizeM = scalFactor * 24
+
+ fontSizeL = scalFactor * 28
+
+ fontSizeXL = scalFactor * 36
+
+ fontSizeXXL = scalFactor * 48
+
+ fontWeight = Font.Light
+
+ if (showClusterIfPossible) {
+ print("Instrument Cluster enabled")
+ withCluster = true
+ clusterWidth = ScreenManager.availableScreens[1].size.width
+ clusterHeight = Math.min(ScreenManager.availableScreens[1].size.width * 0.375, ScreenManager.availableScreens[1].size.height)
+ print("cluster resolution: " + clusterWidth + "x" + clusterHeight)
+ }
+ }
+}
diff --git a/imports/shared/utils/Spacer.qml b/imports/shared/utils/Spacer.qml
new file mode 100644
index 0000000..0322c18
--- /dev/null
+++ b/imports/shared/utils/Spacer.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+
+UIElement {
+ id: root
+ hspan: 1
+ vspan: 1
+ property bool divider: false
+ property alias size: text.font.pixelSize
+
+ Text {
+ id: text
+ anchors.centerIn: parent
+ font.family: Style.fontFamily
+ color: Style.colorWhite
+ font.pixelSize: Style.fontSizeM
+ text: '|'
+ visible: root.divider
+ }
+}
diff --git a/imports/shared/utils/Style.qml b/imports/shared/utils/Style.qml
new file mode 100644
index 0000000..8a6549a
--- /dev/null
+++ b/imports/shared/utils/Style.qml
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.1
+import QtApplicationManager 1.0
+import QtQuick.Window 2.2
+
+QtObject {
+ id: root
+
+ property bool withCluster
+ property bool withPassengerView
+ property int paddingXS
+ property int paddingS
+ property int padding
+ property int paddingL
+ property int paddingXL
+ property int paddingXXL
+
+ property int screenWidth: 1080//Screen.width
+ property int screenHeight: 1920//Screen.height
+ property int bottomBarWidth: screenWidth
+ property int bottomBarHeight: 270
+ property int launchBarHeight: 512
+ property int statusBarHeight: 100
+ property int searchInputHeight: 50
+
+ property int cellWidth
+ property int cellHeight
+ property int tumblerWidth
+ property int buttonRadius
+
+ property string fontFamily
+ property real fontWeight
+ property int fontSizeXXS
+ property int fontSizeXS
+ property int fontSizeS
+ property int fontSizeM
+ property int fontSizeL
+ property int fontSizeXL
+ property int fontSizeXXL
+
+ property color colorWhite
+ property color colorOrange
+ property color colorGrey
+ property color colorBlack
+ property color colorPink
+
+ property color textcolor: '#ffffff'
+
+ property color darkGrey: '#101A1A'
+ property bool debugMode
+ property bool fakeBackground
+ property string displayBackground
+ property real disabledIconOpacity
+
+ property int defaultSymbolSize
+ property int defaultGfxSize
+ property int symbolSizeXS
+ property int symbolSizeS
+ property int symbolSizeM
+ property int symbolSizeL
+
+ property bool clusterWidgetReady: false
+
+ property url drawableUrl: Qt.resolvedUrl('../assets/drawable-ldpi')
+ property url symbolUrl: Qt.resolvedUrl('../assets/icons')
+ property url gfxUrl: Qt.resolvedUrl('../assets/gfx/')
+ property url fonts: Qt.resolvedUrl('../assets/fonts/')
+
+ property bool isClient: typeof ApplicationInterface !== 'undefined'
+ property string styleConfig: isClient ? ApplicationInterface.additionalConfiguration.styleConfig : ApplicationManager.additionalConfiguration.styleConfig
+ property bool showClusterIfPossible: isClient ? ApplicationInterface.additionalConfiguration.showCluster :ApplicationManager.additionalConfiguration.showCluster
+
+ property Loader styleLoader: Loader {
+ property bool showClusterIfPossible: root.showClusterIfPossible
+ source: styleConfig === "auto" ? Qt.resolvedUrl("AutoConfig.qml") : styleConfig
+
+ onLoaded: {
+ print("StyleConfig loaded: ", source)
+ withCluster = configValue("withCluster", true)
+ withPassengerView = configValue("withPassengerView", false)
+ paddingXS = configValue("paddingXS", 2)
+ paddingS = configValue("paddingS", 4)
+ padding = configValue("padding", 10)
+ paddingL = configValue("paddingL", 12)
+ paddingXL = configValue("paddingXL", 16)
+ paddingXXL = configValue("paddingXL", 20)
+
+ cellWidth = configValue("cellWidth", 53)
+ cellHeight = configValue("cellHeight", 33)
+ tumblerWidth = configValue("tumblerWidth", 150)
+ buttonRadius = configValue("buttomRadius", 5)
+
+ fontFamily = configValue("fontFamily", true ? 'Lato' : fontRegular.name)
+ fontWeight = configValue("fontWeight", Font.Light)
+ fontSizeXXS = configValue("fontSizeXXS", 12)
+ fontSizeXS = configValue("fontSizeXS", 18)
+ fontSizeS = configValue("fontSizeS", 24)
+ fontSizeM = configValue("fontSizeM", 28)
+ fontSizeL = configValue("fontSizeL", 38)
+ fontSizeXL = configValue("fontSizeXL", 60)
+ fontSizeXXL = configValue("fontSizeXXL", 80)
+
+ colorWhite = configValue("colorWhite", '#ffffff')
+ colorOrange = configValue("colorOrange", '#f07d00')
+ colorGrey = configValue("colorGrey", '#999999')
+ colorBlack = configValue("colorBlack", '#000000')
+ colorPink = configValue("colorPink", '#EF0080')
+
+ debugMode = configValue("debugMode", false)
+ fakeBackground = configValue("fakeBackground", false)
+ displayBackground = configValue("displayBackground", "background_1280x800")
+ disabledIconOpacity = configValue("disabledIconOpacity", 0.6)
+
+ defaultSymbolSize = configValue("defaultSymbolSize", symbolSizeS)
+ defaultGfxSize = configValue("defaultGfxSize", 1)
+ symbolSizeXS = configValue("symbolSizeXS", 32)
+ symbolSizeS = configValue("symbolSizeS", 48)
+ symbolSizeL = configValue("symbolSizeL", 96)
+ symbolSizeM = configValue("symbolSizeM", 72)
+ }
+ }
+
+ property FontLoader fontRegular: FontLoader {
+ source: font('Lato-Regular')
+ }
+
+ property FontLoader fontLight: FontLoader {
+ source: font('Lato-Light')
+ }
+
+ function configValue(key, defaultValue) {
+ //console.log("configValue: " + key + " = ")
+ //console.log(styleLoader.item[key] ? styleLoader.item[key] : defaultValue)
+ return styleLoader.item[key] ? styleLoader.item[key] : defaultValue
+ }
+
+ function symbol(name, active) {
+ return symbolUrl + '/' + name + '.png'
+ }
+
+ function symbolXS(name, active) {
+ return symbol(name, symbolSizeXS, active);
+ }
+
+ function symbolS(name, active) {
+ return symbol(name, symbolSizeS, active);
+ }
+
+ function symbolM(name, active) {
+ return symbol(name, symbolSizeM, active);
+ }
+
+ function symbolL(name, active) {
+ return symbol(name, symbolSizeL, active);
+ }
+
+ function symbolXL(name, active) {
+ return symbol(name, symbolSizeXL, active);
+ }
+
+ function symbolXXL(name, active) {
+ return symbol(name, symbolSizeXXL, active);
+ }
+
+
+ function gfx2(name) {
+ return gfxUrl + name + '.png'
+ }
+
+ function gfx2Dynamic(name, size) {
+ return gfxUrl + name + '@' + size + 'x.png'
+ }
+
+ function icon(name) {
+ return drawableUrl + '/' + name + '.png';
+ }
+
+ function gfx(name) {
+ return drawableUrl + '/' + name + '.png';
+ }
+
+ function hspan(value) {
+ return cellWidth * value
+ }
+
+ function vspan(value) {
+ return cellHeight * value
+ }
+
+ function asset(name) {
+ return Qt.resolvedUrl('../assets/' + name)
+ }
+
+ function font(name) {
+ return Qt.resolvedUrl('../assets/fonts/' + name + '.ttf')
+ }
+}
diff --git a/imports/shared/utils/Tracer.qml b/imports/shared/utils/Tracer.qml
new file mode 100644
index 0000000..f24ba95
--- /dev/null
+++ b/imports/shared/utils/Tracer.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+
+Item {
+ id: root
+ anchors.fill: parent
+ property color color: '#ac193d'
+ property alias text: note.text
+ property int padding: 1
+ visible: Style.debugMode
+
+ Rectangle {
+ id: frame
+ anchors.fill: parent
+ anchors.margins: root.padding
+ color: 'transparent'
+ border.color: root.color
+ border.width: 2
+ opacity: 0.5
+ }
+
+ Text {
+ id: note
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.margins: 4
+ horizontalAlignment: Text.AlignRight
+ font.pixelSize: 12
+ color: root.color
+ }
+}
diff --git a/imports/shared/utils/UIElement.qml b/imports/shared/utils/UIElement.qml
new file mode 100644
index 0000000..843b3bb
--- /dev/null
+++ b/imports/shared/utils/UIElement.qml
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+import utils 1.0
+
+Item {
+ width: Style.cellWidth * hspan
+ height: Style.cellHeight * vspan
+ property int hspan: 4
+ property int vspan: 1
+
+ property alias _tracer_color: tracer.color
+ property alias _tracer_padding: tracer.padding
+
+ Tracer {
+ id: tracer
+ }
+}
diff --git a/imports/shared/utils/UIScreen.qml b/imports/shared/utils/UIScreen.qml
new file mode 100644
index 0000000..88086da
--- /dev/null
+++ b/imports/shared/utils/UIScreen.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Controls 1.0
+import utils 1.0
+import controls 1.0
+
+UIElement {
+ id: root
+ hspan: 24
+ vspan: 24
+
+ property Component statusItem: Item {}
+ property string title
+ property bool showBack: true
+
+ signal backScreen()
+
+ DisplayBackground {
+ anchors.fill: parent
+ visible: root.parent && root.parent.parent === null
+ }
+
+ Tool {
+ id: backButton
+ z: 5
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: Style.padding
+ visible: root.showBack
+ name: 'back'
+ onClicked: root.backScreen()
+ }
+ Label {
+ anchors.verticalCenter: backButton.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: title
+ font.pixelSize: Style.fontSizeXXL
+ }
+
+}
+
diff --git a/imports/shared/utils/qmldir b/imports/shared/utils/qmldir
new file mode 100644
index 0000000..6202c12
--- /dev/null
+++ b/imports/shared/utils/qmldir
@@ -0,0 +1,12 @@
+singleton Style 1.0 Style.qml
+AutoConfig 1.0 AutoConfig.qml
+Marker 1.0 Marker.qml
+Spacer 1.0 Spacer.qml
+Tracer 1.0 Tracer.qml
+UIElement 1.0 UIElement.qml
+UIPanel 1.0 UIPanel.qml
+UIScreen 1.0 UIScreen.qml
+UIPage 1.0 UIPage.qml
+AppUIScreen 1.0 AppUIScreen.qml
+NavigationUIScreen 1.0 NavigationUIScreen.qml
+Layouter 1.0 Layouter.qml
diff --git a/imports/system/models/ApplicationManagerInterface.qml b/imports/system/models/ApplicationManagerInterface.qml
new file mode 100644
index 0000000..03ff573
--- /dev/null
+++ b/imports/system/models/ApplicationManagerInterface.qml
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Neptune IVI UI.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: GPL-3.0
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.0
+import QtApplicationManager 1.0
+import service.music 1.0
+import utils 1.0
+import com.pelagicore.ScreenManager 1.0
+
+QtObject {
+ id: root
+
+ property string activeAppId
+
+ property variant blackListItems: []
+ property Item windowItem
+ property Item mapWidget
+
+ signal applicationSurfaceReady(Item item)
+ signal releaseApplicationSurface()
+
+ // Cluster signals
+ signal clusterWidgetReady(string category, Item item)
+ signal clusterWidgetActivated(string category, Item item)
+
+ signal passengerWidgetReady(string category, Item item)
+
+ Component.onCompleted: {
+ WindowManager.windowReady.connect(windowReadyHandler)
+ WindowManager.windowClosing.connect(windowClosingHandler)
+ ApplicationManager.applicationWasActivated.connect(applicationActivated)
+ WindowManager.windowLost.connect(windowLostHandler)
+ WindowManager.windowPropertyChanged.connect(windowPropertyChanged)
+ }
+
+ function windowReadyHandler(index, item) {
+ print(":::LaunchController::: WindowManager:windowReadyHandler", index, item)
+ var isInWidgetState = (WindowManager.windowProperty(item, "windowType") === "widgetMap")
+ print(":::LaunchController:::isWidget", isInWidgetState)
+ var isClusterWidget = (WindowManager.windowProperty(item, "windowType") === "clusterWidget")
+ print(":::LaunchController:::isClusterWidget", isClusterWidget)
+ var isPassengerWidget = (WindowManager.windowProperty(item, "windowType") === "passengerWidget")
+ print(":::LaunchController:::isPassengerWidget", isPassengerWidget)
+
+ var acceptWindow = true;
+ var appID = WindowManager.get(index).applicationId;
+
+ if (isInWidgetState) {
+ acceptWindow = false
+ }
+ else if (isClusterWidget) {
+ if (ApplicationManager.additionalConfiguration.showCluster && (WindowManager.runningOnDesktop || ScreenManager.screenCount() > 1)) {
+ if (ApplicationManager.get(appID).categories[0] === "media") {
+ root.clusterWidgetReady("media", item)
+ } else if (ApplicationManager.get(appID).categories[0] === "app") {
+ root.clusterWidgetReady(ApplicationManager.get(appID).categories[1], item)
+ }
+ acceptWindow = false
+ } else {
+ acceptWindow = false
+ item.parent = null
+ }
+ }
+ else if (isPassengerWidget) {
+ if (!Style.withPassengerView) {
+ acceptWindow = false
+ item.parent = null
+ } else {
+ if (ApplicationManager.get(appID).categories[0] === "app") {
+ root.passengerWidgetReady(ApplicationManager.get(appID).categories[1], item)
+ }
+ acceptWindow = false
+ }
+ }
+ else {
+
+ for (var i = 0; i < root.blackListItems.length; ++i) {
+ if (appID === root.blackListItems[i])
+ acceptWindow = false;
+ }
+
+ }
+
+ if (acceptWindow) {
+ root.windowItem = item
+ WindowManager.setWindowProperty(item, "visibility", true)
+
+ root.applicationSurfaceReady(item)
+ } else {
+ if (!item.parent) {
+ item.parent = root.windowItem
+ item.visible = false
+ item.paintingEnabled = false
+ }
+ }
+ }
+
+ function windowPropertyChanged(window, name, value) {
+ print(":::LaunchController::: WindowManager:windowPropertyChanged", window, name, value)
+ if (name === "visibility" && value === false) {
+ root.releaseApplicationSurface()
+ }
+ }
+
+ function windowClosingHandler(index, item) {
+ if (item === root.windowItem) { // start close animation
+ root.releaseApplicationSurface()
+ }
+ }
+
+ function windowLostHandler(index, item) {
+ WindowManager.releaseWindow(item) // immediately close anything which is not handled by this container
+ }
+
+ function applicationActivated(appId, appAliasId) {
+ print(":::LaunchController::: WindowManager:raiseApplicationWindow" + appId + " " + WindowManager.count)
+ root.activeAppId = appId
+ for (var i = 0; i < WindowManager.count; i++) {
+ if (WindowManager.get(i).applicationId === appId) {
+ var item = WindowManager.get(i).windowItem
+ print(":::LaunchController::: App found. Running the app " + appId + " Item: " + item)
+ var isWidget = (WindowManager.windowProperty(item, "windowType") === "widget")
+ var isMapWidget = (WindowManager.windowProperty(item, "windowType") === "widgetMap")
+ var isClusterWidget = (WindowManager.windowProperty(item, "windowType") === "clusterWidget")
+ var isPassengerWidget = (WindowManager.windowProperty(item, "windowType") === "passengerWidget")
+ print(":::LaunchController:::isClusterWidget", isClusterWidget)
+ print(":::LaunchController:::isPassengerWidget", isPassengerWidget)
+ print(":::LaunchController:::isWidget", isWidget, isMapWidget)
+
+ if (isClusterWidget) {
+ if (ApplicationManager.get(appId).categories[0] === "app") {
+ root.clusterWidgetActivated(ApplicationManager.get(appId).categories[1], item)
+ }
+ break
+ }
+
+ if (!isMapWidget && !isClusterWidget && !isPassengerWidget) {
+ WindowManager.setWindowProperty(item, "visibility", true)
+ root.windowItem = item
+ root.applicationSurfaceReady(item)
+ }
+ }
+ }
+ }
+}
diff --git a/imports/system/models/qmldir b/imports/system/models/qmldir
new file mode 100644
index 0000000..e947d97
--- /dev/null
+++ b/imports/system/models/qmldir
@@ -0,0 +1 @@
+singleton ApplicationManagerInterface 1.0 ApplicationManagerInterface.qml
diff --git a/kms_config.json b/kms_config.json
new file mode 100644
index 0000000..232a7a2
--- /dev/null
+++ b/kms_config.json
@@ -0,0 +1,14 @@
+{
+ "device": "drm-nvdc",
+ "separateScreens": true,
+ "outputs": [
+ {
+ "name": "HDMI1",
+ "virtualIndex": 0,
+ "physicalWidth": 1080,
+ "physicalHeight": 1920,
+ "virtualPos": "0, 0"
+ }
+ ]
+}
+
diff --git a/scripts/automotivedemo.service b/scripts/automotivedemo.service
new file mode 100644
index 0000000..2e73b1d
--- /dev/null
+++ b/scripts/automotivedemo.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=AutomotiveDemo
+After=systemd-user-sessions.service
+
+[Service]
+ExecStart=/opt/automotivedemo/start.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/start.sh b/start.sh
new file mode 100644
index 0000000..3931eaf
--- /dev/null
+++ b/start.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+export QT_QPA_EGLFS_KMS_CONFIG=kms_config.json
+cd /opt/automotivedemo
+/usr/bin/appcontroller /usr/bin/appman -r -c /opt/am/config.yaml -c am-config.yaml --dbus none Main.qml
+