C
Qt Cluster: Rendering and Recovery from Main UI Failure
// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause // This file is part of the Qt Safe Renderer module import QtQuick import ClusterDemo DashboardSportForm { id: main //the id is used in e.g. VehicleInfoNote //Start animating gauges after both are loaded function showGauges() { if (speedoMeter.status === Loader.Ready && flipable.rpm.status === Loader.Ready) { startupAnimation.start() } } property var component: [ "../MapView.qml", "../MediaPlayerView.qml", "../ConsumptionView.qml", "", // VideoView.qml "../CarParking.qml", "" // CarView.qml ] property string mapPositionImage: "image://etc/MapLocationSport.png" property int videoviewindex: 3 property int parkingviewindex: 4 property int carviewindex: 5 property int preReversingCenterView: -1 property int preReversingRightView // CarModel animations property int carModelHighlightType: 0 property bool doorAction: false property bool actionInProgress: false property bool loadingInProgress: false property bool isReversing: false property int doorsOpen: ValueSource.frontLeftOpen + ValueSource.frontRightOpen + ValueSource.hoodOpen + ValueSource.trunkOpen property bool flatTire: ValueSource.flatTire property bool lightFailure: ValueSource.lightFailure property int gear: ValueSource ? ValueSource.gear : "4" property var cameraView: camera property bool viewChanged: ValueSource.viewChange property color iconRed: "#e41e25" property color iconGreen: "#5caa15" property color iconYellow: "#face20" property color iconDark: "#444444" speedText.text: ValueSource.kph.toFixed().toString() iconCoolant.color: main.iconDark iconBattery.color: main.iconDark iconFuel.color: main.iconDark iconParkingBrake.color: main.iconDark iconLights.color: main.iconDark iconLowbeam.color: main.iconDark iconTyre.color: main.iconDark iconLamp.color: main.iconDark iconSeatbelt.color: main.iconDark function forceCarView() { actionInProgress = true // Make CarView visible before activating the animations if (car.item && car.item.hidden) { if (camera.visible) camera.visible = false car.opacity = 1.0 centerStack.visible = false car.visible = true car.item.hidden = false } } function loadCenterView(nextView, allowParking) { loadingInProgress = true var previousViewIndex = centerStack.viewIndex if (preReversingCenterView != -1 && !allowParking) { if (centerStack.viewIndex !== preReversingCenterView) { centerStack.viewIndex = preReversingCenterView if (centerStack.viewIndex < 0) centerStack.viewIndex = 5 } } else { centerStack.viewIndex = getViewIndex(centerStack.viewIndex, nextView, allowParking) } loadingInProgress = false if (previousViewIndex === carviewindex) centerStack.fadeOutCenter.target = car else if (previousViewIndex === videoviewindex) centerStack.fadeOutCenter.target = camera else centerStack.fadeOutCenter.target = centerStack.loader centerStack.fadeOutCenter.start() } function getViewIndex(viewindex, nextView, allowParking) { if (allowParking) { return videoviewindex } if (nextView) { viewindex++ if (viewindex === parkingviewindex) { viewindex++ } if (viewindex > 5) viewindex = 0 } else { viewindex-- if (viewindex === parkingviewindex) { viewindex-- } if (viewindex < 0) viewindex = 5 } return viewindex } onDoorsOpenChanged: { if (actionInProgress && !doorAction) return // Check all doors & parse a correct value from them var doors = 0 if (ValueSource.frontLeftOpen) doors ^= 1 if (ValueSource.frontRightOpen) doors ^= 2 if (ValueSource.trunkOpen) doors ^= 4 if (ValueSource.hoodOpen) doors ^= 8 if (doors != 0) { forceCarView() if (car.item) car.item.highlightDoors(doors) carModelHighlightType = -1 } } onFlatTireChanged: { if (!actionInProgress && flatTire) { forceCarView() carModelHighlightType = car.item.highlightTire() } } onLightFailureChanged: { if (!actionInProgress && lightFailure) { forceCarView() carModelHighlightType = car.item.highlightLamp() } } onGearChanged: { if (gear === -1) reversing() else if (gear >= 0) returnFromReversing() } onViewChangedChanged: changeView(viewChanged) function reversing() { isReversing = true // Car backing up, trigger rear camera view and proximity sensor view preReversingCenterView = centerStack.viewIndex loadCenterView(0, true) flipable.flipped = !flipable.flipped } function returnFromReversing() { if (!isReversing) return loadCenterView(true, false) preReversingCenterView = -1 flipable.flipped = !flipable.flipped isReversing = false } function changeView(nextView) { if (isReversing) return if (actionInProgress || loadingInProgress) return if (nextView) loadCenterView(nextView) } function stopAll() { returnView.stop() startupAnimation.stop() centerStack.fadeOutCenter.stop() centerStack.fadeInCenter.stop() doorAction = false actionInProgress = false loadingInProgress = false isReversing = false } Timer { id: returnView interval: 1000 running: false onTriggered: { if (camera.x === centerStack.x) camera.visible = true car.item.hidden = true car.visible = false car.opacity = 0.0 centerStack.visible = true } } SequentialAnimation { id: startupAnimation ParallelAnimation { SmoothedAnimation { target: speedoMeter.rotation property: "angle" from: 90 to: 0 duration: 300 } SmoothedAnimation { target: flipable.flipRotation property: "angle" from: 90 to: 0 duration: 300 } } ParallelAnimation { SequentialAnimation { id: rpmAnimation SmoothedAnimation { target: flipable.rpm.item property: "rpmValue" to: flipable.rpm.item.maxValue duration: gaugeDemoTime easing.type: Easing.InQuint } SmoothedAnimation { target: flipable.rpm.item property: "rpmValue" to: ValueSource.rpm duration: gaugeDemoTime easing.type: Easing.OutQuint } ScriptAction { script: flipable.rpm.item.rpmValue = ValueSource.rpm } } SequentialAnimation { id: speedAnimation SmoothedAnimation { target: speedoMeter.item property: "speedValue" to: speedoMeter.item.maxValue duration: gaugeDemoTime easing.type: Easing.InQuint } SmoothedAnimation { target: speedoMeter.item property: "speedValue" to: ValueSource.kph // TODO: Not entirely accurate this way, fix duration: gaugeDemoTime easing.type: Easing.OutQuint } ScriptAction { script: startupAnimationStopped = true } } } } speedoMeter.onLoaded: showGauges() flipable.onLoaded: showGauges() }