feat: Visual upgrades, Dallas sensor backend, and docs
This commit is contained in:
721
TemperatureGauge.qml
Normal file
721
TemperatureGauge.qml
Normal file
@@ -0,0 +1,721 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Shapes
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 480
|
||||
height: 480
|
||||
|
||||
property real currentTemp: 0 // Bound in main.qml
|
||||
onCurrentTempChanged: console.log("QML Left Temp Updated: " + currentTemp)
|
||||
|
||||
property real currentRightTemp: 0 // Bound in main.qml
|
||||
property bool startupComplete: true
|
||||
|
||||
// Sweep Property for Startup - REMOVED
|
||||
// property real sweepTemp: -15
|
||||
|
||||
// Startup Sweep Animation - REMOVED
|
||||
// SequentialAnimation { ... }
|
||||
|
||||
Component.onCompleted: {
|
||||
forceActiveFocus()
|
||||
root.startupComplete = true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
// color: "#050505" // Old solid color
|
||||
|
||||
// Gradient for depth (Vertical Linear)
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: "black" }
|
||||
GradientStop { position: 0.5; color: "#1a1a1a" } // Lighter center strip
|
||||
GradientStop { position: 1.0; color: "black" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- Left Gauge (Temperature) ---
|
||||
Item {
|
||||
id: leftGauge
|
||||
anchors.fill: parent
|
||||
|
||||
// Track Outline
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// Anti-aliasing for smoother lines
|
||||
// layer.enabled: true
|
||||
// layer.samples: 4
|
||||
// layer.smooth: true
|
||||
|
||||
ShapePath {
|
||||
strokeColor: "white"
|
||||
strokeWidth: 2
|
||||
fillColor: "transparent"
|
||||
capStyle: ShapePath.FlatCap
|
||||
|
||||
// Outer Arc (145 to 215 degrees)
|
||||
// 145 deg = 0.8055 PI
|
||||
// 215 deg = 1.1944 PI
|
||||
startX: 240 + 210 * Math.cos(Math.PI * (145/180))
|
||||
startY: 240 + 210 * Math.sin(Math.PI * (145/180))
|
||||
|
||||
PathArc {
|
||||
x: 240 + 210 * Math.cos(Math.PI * (215/180))
|
||||
y: 240 + 210 * Math.sin(Math.PI * (215/180))
|
||||
radiusX: 210; radiusY: 210
|
||||
useLargeArc: false
|
||||
}
|
||||
|
||||
// Bottom Line connecting to inner
|
||||
PathLine {
|
||||
x: 240 + 160 * Math.cos(Math.PI * (215/180))
|
||||
y: 240 + 160 * Math.sin(Math.PI * (215/180))
|
||||
}
|
||||
|
||||
// Inner Arc
|
||||
PathArc {
|
||||
x: 240 + 160 * Math.cos(Math.PI * (145/180))
|
||||
y: 240 + 160 * Math.sin(Math.PI * (145/180))
|
||||
radiusX: 160; radiusY: 160
|
||||
useLargeArc: false
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
|
||||
// Top Line connecting back to start
|
||||
PathLine {
|
||||
x: 240 + 210 * Math.cos(Math.PI * (145/180))
|
||||
y: 240 + 210 * Math.sin(Math.PI * (145/180))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Indicator (Blue Bar)
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// layer.enabled: true
|
||||
// layer.samples: 4
|
||||
|
||||
ShapePath {
|
||||
strokeColor: "transparent"
|
||||
fillColor: "#2196F3" // Blue
|
||||
|
||||
// Range -15 to 0.
|
||||
// -15 = 145 deg
|
||||
// 0 = 171.25 deg
|
||||
startX: 240 + 205 * Math.cos(Math.PI * (145/180))
|
||||
startY: 240 + 205 * Math.sin(Math.PI * (145/180))
|
||||
|
||||
PathArc {
|
||||
x: 240 + 205 * Math.cos(Math.PI * (171.25/180))
|
||||
y: 240 + 205 * Math.sin(Math.PI * (171.25/180))
|
||||
radiusX: 205; radiusY: 205
|
||||
}
|
||||
PathLine {
|
||||
x: 240 + 165 * Math.cos(Math.PI * (171.25/180))
|
||||
y: 240 + 165 * Math.sin(Math.PI * (171.25/180))
|
||||
}
|
||||
PathArc {
|
||||
x: 240 + 165 * Math.cos(Math.PI * (145/180))
|
||||
y: 240 + 165 * Math.sin(Math.PI * (145/180))
|
||||
radiusX: 165; radiusY: 165
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
x: 240 + 205 * Math.cos(Math.PI * (145/180))
|
||||
y: 240 + 205 * Math.sin(Math.PI * (145/180))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temperature Markers & Ticks
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// layer.enabled: true
|
||||
// layer.samples: 4
|
||||
ShapePath {
|
||||
strokeColor: "white"
|
||||
strokeWidth: 2
|
||||
fillColor: "transparent"
|
||||
|
||||
// -15 @ 145 deg
|
||||
startX: 240 + 210 * Math.cos(Math.PI * (145/180))
|
||||
startY: 240 + 210 * Math.sin(Math.PI * (145/180))
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (145/180)); y: 240 + 215 * Math.sin(Math.PI * (145/180)) }
|
||||
|
||||
// -10 @ 153.75 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (153.75/180)); y: 240 + 210 * Math.sin(Math.PI * (153.75/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (153.75/180)); y: 240 + 215 * Math.sin(Math.PI * (153.75/180)) }
|
||||
|
||||
// -5 @ 162.5 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (162.5/180)); y: 240 + 210 * Math.sin(Math.PI * (162.5/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (162.5/180)); y: 240 + 215 * Math.sin(Math.PI * (162.5/180)) }
|
||||
|
||||
// 0 @ 171.25 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (171.25/180)); y: 240 + 210 * Math.sin(Math.PI * (171.25/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (171.25/180)); y: 240 + 215 * Math.sin(Math.PI * (171.25/180)) }
|
||||
|
||||
// 5 @ 180 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * 1.0); y: 240 + 210 * Math.sin(Math.PI * 1.0) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * 1.0); y: 240 + 215 * Math.sin(Math.PI * 1.0) }
|
||||
|
||||
// 10 @ 188.75 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (188.75/180)); y: 240 + 210 * Math.sin(Math.PI * (188.75/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (188.75/180)); y: 240 + 215 * Math.sin(Math.PI * (188.75/180)) }
|
||||
|
||||
// 15 @ 197.5 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (197.5/180)); y: 240 + 210 * Math.sin(Math.PI * (197.5/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (197.5/180)); y: 240 + 215 * Math.sin(Math.PI * (197.5/180)) }
|
||||
|
||||
// 20 @ 206.25 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (206.25/180)); y: 240 + 210 * Math.sin(Math.PI * (206.25/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (206.25/180)); y: 240 + 215 * Math.sin(Math.PI * (206.25/180)) }
|
||||
|
||||
// 25 @ 215 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (215/180)); y: 240 + 210 * Math.sin(Math.PI * (215/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (215/180)); y: 240 + 215 * Math.sin(Math.PI * (215/180)) }
|
||||
}
|
||||
}
|
||||
|
||||
// -15 @ 145 deg
|
||||
Text {
|
||||
text: "-15"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (145/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (145/180)) - height/2
|
||||
}
|
||||
// -10 @ 153.75 deg
|
||||
Text {
|
||||
text: "-10"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (153.75/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (153.75/180)) - height/2
|
||||
}
|
||||
// -5 @ 162.5 deg
|
||||
Text {
|
||||
text: "-5"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (162.5/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (162.5/180)) - height/2
|
||||
}
|
||||
// 0 @ 171.25 deg
|
||||
Text {
|
||||
text: "0"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (171.25/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (171.25/180)) - height/2
|
||||
}
|
||||
// 5 @ 180 deg
|
||||
Text {
|
||||
text: "5"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * 1.0) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * 1.0) - height/2
|
||||
}
|
||||
// 10 @ 188.75 deg
|
||||
Text {
|
||||
text: "10"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (188.75/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (188.75/180)) - height/2
|
||||
}
|
||||
// 15 @ 197.5 deg
|
||||
Text {
|
||||
text: "15"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (197.5/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (197.5/180)) - height/2
|
||||
}
|
||||
// 20 @ 206.25 deg
|
||||
Text {
|
||||
text: "20"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (206.25/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (206.25/180)) - height/2
|
||||
}
|
||||
// 25 @ 215 deg
|
||||
Text {
|
||||
text: "25"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (215/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (215/180)) - height/2
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// --- Right Gauge (Mirrored) ---
|
||||
Item {
|
||||
id: rightGauge
|
||||
anchors.fill: parent
|
||||
|
||||
// Track Outline
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// layer.enabled: true
|
||||
// layer.samples: 4
|
||||
// layer.smooth: true
|
||||
|
||||
ShapePath {
|
||||
strokeColor: "white"
|
||||
strokeWidth: 2
|
||||
fillColor: "transparent"
|
||||
capStyle: ShapePath.FlatCap
|
||||
|
||||
// Outer Arc (35 to -35 degrees)
|
||||
// 35 deg = 0.1944 PI
|
||||
// -35 deg = 325 deg = 1.8055 PI
|
||||
|
||||
startX: 240 + 210 * Math.cos(Math.PI * (325/180))
|
||||
startY: 240 + 210 * Math.sin(Math.PI * (325/180))
|
||||
|
||||
PathArc {
|
||||
x: 240 + 210 * Math.cos(Math.PI * (35/180))
|
||||
y: 240 + 210 * Math.sin(Math.PI * (35/180))
|
||||
radiusX: 210; radiusY: 210
|
||||
useLargeArc: false
|
||||
}
|
||||
|
||||
// Bottom Line connecting to inner
|
||||
PathLine {
|
||||
x: 240 + 160 * Math.cos(Math.PI * (35/180))
|
||||
y: 240 + 160 * Math.sin(Math.PI * (35/180))
|
||||
}
|
||||
|
||||
// Inner Arc
|
||||
PathArc {
|
||||
x: 240 + 160 * Math.cos(Math.PI * (325/180))
|
||||
y: 240 + 160 * Math.sin(Math.PI * (325/180))
|
||||
radiusX: 160; radiusY: 160
|
||||
useLargeArc: false
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
|
||||
// Top Line connecting back to start
|
||||
PathLine {
|
||||
x: 240 + 210 * Math.cos(Math.PI * (325/180))
|
||||
y: 240 + 210 * Math.sin(Math.PI * (325/180))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Indicator (Blue Bar)
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// layer.enabled: true
|
||||
// layer.samples: 4
|
||||
|
||||
ShapePath {
|
||||
strokeColor: "transparent"
|
||||
fillColor: "#2196F3" // Blue
|
||||
|
||||
// Range -15 to 0.
|
||||
// -15 = 35 deg
|
||||
// 0 = 8.75 deg
|
||||
startX: 240 + 205 * Math.cos(Math.PI * (35/180))
|
||||
startY: 240 + 205 * Math.sin(Math.PI * (35/180))
|
||||
|
||||
PathArc {
|
||||
x: 240 + 205 * Math.cos(Math.PI * (8.75/180))
|
||||
y: 240 + 205 * Math.sin(Math.PI * (8.75/180))
|
||||
radiusX: 205; radiusY: 205
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
x: 240 + 165 * Math.cos(Math.PI * (8.75/180))
|
||||
y: 240 + 165 * Math.sin(Math.PI * (8.75/180))
|
||||
}
|
||||
PathArc {
|
||||
x: 240 + 165 * Math.cos(Math.PI * (35/180))
|
||||
y: 240 + 165 * Math.sin(Math.PI * (35/180))
|
||||
radiusX: 165; radiusY: 165
|
||||
}
|
||||
PathLine {
|
||||
x: 240 + 205 * Math.cos(Math.PI * (35/180))
|
||||
y: 240 + 205 * Math.sin(Math.PI * (35/180))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Markers & Ticks
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// layer.enabled: true
|
||||
// layer.samples: 4
|
||||
ShapePath {
|
||||
strokeColor: "white"
|
||||
strokeWidth: 2
|
||||
fillColor: "transparent"
|
||||
|
||||
// -15 @ 35 deg
|
||||
startX: 240 + 210 * Math.cos(Math.PI * (35/180))
|
||||
startY: 240 + 210 * Math.sin(Math.PI * (35/180))
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (35/180)); y: 240 + 215 * Math.sin(Math.PI * (35/180)) }
|
||||
|
||||
// -10 @ 26.25 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (26.25/180)); y: 240 + 210 * Math.sin(Math.PI * (26.25/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (26.25/180)); y: 240 + 215 * Math.sin(Math.PI * (26.25/180)) }
|
||||
|
||||
// -5 @ 17.5 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (17.5/180)); y: 240 + 210 * Math.sin(Math.PI * (17.5/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (17.5/180)); y: 240 + 215 * Math.sin(Math.PI * (17.5/180)) }
|
||||
|
||||
// 0 @ 8.75 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (8.75/180)); y: 240 + 210 * Math.sin(Math.PI * (8.75/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (8.75/180)); y: 240 + 215 * Math.sin(Math.PI * (8.75/180)) }
|
||||
|
||||
// 5 @ 0 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(0); y: 240 + 210 * Math.sin(0) }
|
||||
PathLine { x: 240 + 215 * Math.cos(0); y: 240 + 215 * Math.sin(0) }
|
||||
|
||||
// 10 @ -8.75 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (-8.75/180)); y: 240 + 210 * Math.sin(Math.PI * (-8.75/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (-8.75/180)); y: 240 + 215 * Math.sin(Math.PI * (-8.75/180)) }
|
||||
|
||||
// 15 @ -17.5 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (-17.5/180)); y: 240 + 210 * Math.sin(Math.PI * (-17.5/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (-17.5/180)); y: 240 + 215 * Math.sin(Math.PI * (-17.5/180)) }
|
||||
|
||||
// 20 @ -26.25 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (-26.25/180)); y: 240 + 210 * Math.sin(Math.PI * (-26.25/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (-26.25/180)); y: 240 + 215 * Math.sin(Math.PI * (-26.25/180)) }
|
||||
|
||||
// 25 @ -35 deg
|
||||
PathMove { x: 240 + 210 * Math.cos(Math.PI * (-35/180)); y: 240 + 210 * Math.sin(Math.PI * (-35/180)) }
|
||||
PathLine { x: 240 + 215 * Math.cos(Math.PI * (-35/180)); y: 240 + 215 * Math.sin(Math.PI * (-35/180)) }
|
||||
}
|
||||
}
|
||||
|
||||
// -15 @ 35 deg
|
||||
Text {
|
||||
text: "-15"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (35/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (35/180)) - height/2
|
||||
}
|
||||
// -10 @ 26.25 deg
|
||||
Text {
|
||||
text: "-10"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (26.25/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (26.25/180)) - height/2
|
||||
}
|
||||
// -5 @ 17.5 deg
|
||||
Text {
|
||||
text: "-5"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (17.5/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (17.5/180)) - height/2
|
||||
}
|
||||
// 0 @ 8.75 deg
|
||||
Text {
|
||||
text: "0"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (8.75/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (8.75/180)) - height/2
|
||||
}
|
||||
// 5 @ 0 deg
|
||||
Text {
|
||||
text: "5"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(0) - width/2
|
||||
y: 240 + 230 * Math.sin(0) - height/2
|
||||
}
|
||||
// 10 @ -8.75 deg
|
||||
Text {
|
||||
text: "10"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (-8.75/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (-8.75/180)) - height/2
|
||||
}
|
||||
// 15 @ -17.5 deg
|
||||
Text {
|
||||
text: "15"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (-17.5/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (-17.5/180)) - height/2
|
||||
}
|
||||
// 20 @ -26.25 deg
|
||||
Text {
|
||||
text: "20"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (-26.25/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (-26.25/180)) - height/2
|
||||
}
|
||||
// 25 @ -35 deg
|
||||
Text {
|
||||
text: "25"
|
||||
color: "white"
|
||||
font.pixelSize: 20
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
x: 240 + 230 * Math.cos(Math.PI * (-35/180)) - width/2
|
||||
y: 240 + 230 * Math.sin(Math.PI * (-35/180)) - height/2
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// --- Center Cover Shape ---
|
||||
Shape {
|
||||
anchors.fill: parent
|
||||
// layer.enabled: true
|
||||
// layer.samples: 4
|
||||
z: 1 // Above background, below text/needles
|
||||
|
||||
ShapePath {
|
||||
strokeColor: "#333333" // Subtle outline
|
||||
strokeWidth: 1
|
||||
fillColor: "#111111" // Slightly lighter than black
|
||||
|
||||
// Top Arc (225 to 315 degrees)
|
||||
startX: 240 + 210 * Math.cos(Math.PI * 1.25) // 225 deg
|
||||
startY: 240 + 210 * Math.sin(Math.PI * 1.25)
|
||||
|
||||
PathArc {
|
||||
x: 240 + 210 * Math.cos(Math.PI * 1.75) // 315 deg
|
||||
y: 240 + 210 * Math.sin(Math.PI * 1.75)
|
||||
radiusX: 210; radiusY: 210
|
||||
}
|
||||
|
||||
// Right Side (Straight lines)
|
||||
// Line to Top-Right Waist
|
||||
PathLine {
|
||||
x: 240 + 90
|
||||
y: 240 - 80
|
||||
}
|
||||
// Vertical Line down
|
||||
PathLine {
|
||||
x: 240 + 90
|
||||
y: 240 + 80
|
||||
}
|
||||
// Line to Bottom Arc Start (45 deg)
|
||||
PathLine {
|
||||
x: 240 + 210 * Math.cos(Math.PI * 0.25)
|
||||
y: 240 + 210 * Math.sin(Math.PI * 0.25)
|
||||
}
|
||||
|
||||
// Bottom Arc (45 to 135 degrees)
|
||||
PathArc {
|
||||
x: 240 + 210 * Math.cos(Math.PI * 0.75) // 135 deg
|
||||
y: 240 + 210 * Math.sin(Math.PI * 0.75)
|
||||
radiusX: 210; radiusY: 210
|
||||
}
|
||||
|
||||
// Left Side (Straight lines)
|
||||
// Line to Bottom-Left Waist
|
||||
PathLine {
|
||||
x: 240 - 90
|
||||
y: 240 + 80
|
||||
}
|
||||
// Vertical Line up
|
||||
PathLine {
|
||||
x: 240 - 90
|
||||
y: 240 - 80
|
||||
}
|
||||
// Line back to Top Arc Start (225 deg)
|
||||
PathLine {
|
||||
x: 240 + 210 * Math.cos(Math.PI * 1.25)
|
||||
y: 240 + 210 * Math.sin(Math.PI * 1.25)
|
||||
}
|
||||
}
|
||||
|
||||
// Inner Glow / Highlight on the cover
|
||||
ShapePath {
|
||||
strokeColor: "transparent"
|
||||
fillColor: "transparent" // Placeholder for an effect if needed
|
||||
}
|
||||
}
|
||||
|
||||
// --- Center Details ---
|
||||
Text {
|
||||
text: "VOLVO"
|
||||
font.pixelSize: 28
|
||||
font.bold: true
|
||||
font.family: "Serif"
|
||||
color: "white"
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 100
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
z: 2 // Ensure on top of cover
|
||||
}
|
||||
|
||||
// Unit Symbol (Moved to root to be above center cover)
|
||||
Text {
|
||||
text: "°C"
|
||||
color: "orange"
|
||||
font.pixelSize: 28
|
||||
font.family: "Arial"
|
||||
font.bold: true
|
||||
z: 10 // Above center cover
|
||||
anchors.centerIn: parent
|
||||
anchors.verticalCenterOffset: -40 // Above center
|
||||
}
|
||||
|
||||
// --- Needles ---
|
||||
|
||||
component GaugeNeedle : Item {
|
||||
id: needleComponent
|
||||
property real angle: 0
|
||||
property color needleColor: "#FF6600"
|
||||
|
||||
x: 240
|
||||
y: 240
|
||||
width: 1
|
||||
height: 1
|
||||
|
||||
// Glow/Shadow effect behind needle
|
||||
Rectangle {
|
||||
width: 180
|
||||
height: 12
|
||||
color: needleComponent.needleColor
|
||||
opacity: 0.3
|
||||
radius: 6
|
||||
y: -height / 2
|
||||
x: 0
|
||||
transform: Rotation {
|
||||
origin.x: 0
|
||||
origin.y: 6
|
||||
angle: needleComponent.angle
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: needleRect
|
||||
width: 180
|
||||
height: 4 // Thinner for sharper look
|
||||
color: needleComponent.needleColor
|
||||
radius: 2
|
||||
antialiasing: true
|
||||
|
||||
y: -height / 2
|
||||
x: 0 // Starts at center and extends outwards
|
||||
|
||||
transform: Rotation {
|
||||
origin.x: 0
|
||||
origin.y: needleRect.height / 2
|
||||
angle: needleComponent.angle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getAngleFromTemp(temp) {
|
||||
// Range -15 to 25 (40 deg range)
|
||||
// Span 70 degrees (145 to 215)
|
||||
// 70 / 40 = 1.75 degrees per unit
|
||||
return 145 + (temp + 15) * 1.75
|
||||
}
|
||||
|
||||
function getRightAngleFromTemp(temp) {
|
||||
// Range -15 to 25
|
||||
// Span 70 degrees (35 to -35)
|
||||
return 35 - (temp + 15) * 1.75
|
||||
}
|
||||
|
||||
// Keyboard Control
|
||||
focus: true
|
||||
Keys.onUpPressed: {
|
||||
if (root.startupComplete) {
|
||||
root.currentTemp = Math.min(root.currentTemp + 2, 25)
|
||||
}
|
||||
}
|
||||
Keys.onDownPressed: {
|
||||
if (root.startupComplete) {
|
||||
root.currentTemp = Math.max(root.currentTemp - 2, -15)
|
||||
}
|
||||
}
|
||||
Keys.onPressed: (event) => {
|
||||
if (!root.startupComplete) return;
|
||||
|
||||
if (event.key === Qt.Key_PageUp) {
|
||||
root.currentRightTemp = Math.min(root.currentRightTemp + 2, 25)
|
||||
event.accepted = true
|
||||
} else if (event.key === Qt.Key_PageDown) {
|
||||
root.currentRightTemp = Math.max(root.currentRightTemp - 2, -15)
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
GaugeNeedle {
|
||||
id: leftNeedle
|
||||
// If startup complete, use real temp. Else use sweep temp.
|
||||
angle: root.getAngleFromTemp(root.startupComplete ? root.currentTemp : -15)
|
||||
|
||||
Behavior on angle {
|
||||
// Slower, smoother damping for a "heavy" gauge feel
|
||||
SpringAnimation { spring: 2; damping: 0.2; epsilon: 0.1 }
|
||||
}
|
||||
}
|
||||
|
||||
GaugeNeedle {
|
||||
id: rightNeedle
|
||||
angle: root.getRightAngleFromTemp(root.startupComplete ? root.currentRightTemp : -15)
|
||||
|
||||
Behavior on angle {
|
||||
SpringAnimation { spring: 2; damping: 0.2; epsilon: 0.1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user