diff options
author | Suchinton Chakravarty <suchinton.2001@gmail.com> | 2024-09-15 23:31:58 +0530 |
---|---|---|
committer | Suchinton Chakravarty <suchinton.2001@gmail.com> | 2024-09-29 23:31:52 +0530 |
commit | 65d4619371979c8921ff155a6fe1d7de0e1d3598 (patch) | |
tree | defb38b033c88338b609c4b9ecc0edd55cb23124 | |
parent | b0844193f37f477c9e7e509e0b4eaf221886192b (diff) |
Add New Custom Gauges and CARLA playback refactored
- This commit adds new custom QML Gauges for Engine RPM, Speed, Fuel level and Coolant temp
- Improve Exception handling for CARLA playback
- Add the RPM and Speed Gauge elements
- Update the functions resp. for updating their values
- Fix Alignment of backgrounds, font size and progress bar
- Update Half Gauge to have progress ticks
- Add gauges to the main IC page
Bug-AGL: SPEC-5161
Change-Id: I52274afb7ea95c812c539a0b21305ad078d5dadb
Signed-off-by: Suchinton Chakravarty <suchinton.2001@gmail.com>
-rw-r--r-- | Main_Window.ui | 16 | ||||
-rw-r--r-- | QMLWidgets/Full_Gauge/RPMGauge.qml | 165 | ||||
-rw-r--r-- | QMLWidgets/Full_Gauge/SpeedGauge.qml | 202 | ||||
-rw-r--r-- | QMLWidgets/Full_Gauge/assets/Ellipse 1.svg | 11 | ||||
-rw-r--r-- | QMLWidgets/Full_Gauge/assets/Ellipse 5.svg | 24 | ||||
-rw-r--r-- | QMLWidgets/Half_Gauge/CoolantGauge.qml | 150 | ||||
-rw-r--r-- | QMLWidgets/Half_Gauge/FuelGauge.qml | 158 | ||||
-rw-r--r-- | Scripts/record_playback.py | 1 | ||||
-rw-r--r-- | Widgets/ICPage.py | 91 | ||||
-rw-r--r-- | Widgets/Keypad.py | 53 | ||||
-rw-r--r-- | requirements.txt | 4 | ||||
-rw-r--r-- | ui/IC.ui | 822 | ||||
-rw-r--r-- | ui/Keypad.ui | 316 |
13 files changed, 1504 insertions, 509 deletions
diff --git a/Main_Window.ui b/Main_Window.ui index 71fe4a4..41500a8 100644 --- a/Main_Window.ui +++ b/Main_Window.ui @@ -9,10 +9,16 @@ <rect> <x>0</x> <y>0</y> - <width>903</width> - <height>705</height> + <width>1600</width> + <height>900</height> </rect> </property> + <property name="minimumSize"> + <size> + <width>1600</width> + <height>900</height> + </size> + </property> <property name="palette"> <palette> <active> @@ -153,7 +159,7 @@ </colorrole> <colorrole role="PlaceholderText"> <brush brushstyle="SolidPattern"> - <color alpha="255"> + <color alpha="128"> <red>255</red> <green>255</green> <blue>255</blue> @@ -299,7 +305,7 @@ </colorrole> <colorrole role="PlaceholderText"> <brush brushstyle="SolidPattern"> - <color alpha="255"> + <color alpha="128"> <red>255</red> <green>255</green> <blue>255</blue> @@ -445,7 +451,7 @@ </colorrole> <colorrole role="PlaceholderText"> <brush brushstyle="SolidPattern"> - <color alpha="255"> + <color alpha="128"> <red>255</red> <green>255</green> <blue>255</blue> diff --git a/QMLWidgets/Full_Gauge/RPMGauge.qml b/QMLWidgets/Full_Gauge/RPMGauge.qml new file mode 100644 index 0000000..382731d --- /dev/null +++ b/QMLWidgets/Full_Gauge/RPMGauge.qml @@ -0,0 +1,165 @@ +import QtQuick 2.9
+
+Item {
+ id: root
+ width: 400
+ height: 400
+
+ property real value: 0
+ property real minValue: 0
+ property real maxValue: 8000
+ property string unit: "RPM"
+
+ property color primaryColor: "#16CCBA"
+ property color secondaryColor: "#00000000"
+ property int animationDuration: 1000
+ property real startAngle: 0
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#041F2B"
+ z: -1
+ }
+
+ Image {
+ id: background1
+ source: "./assets/Ellipse 5.svg"
+ rotation: 180
+ sourceSize.width: width
+ sourceSize.height: width
+ fillMode: Image.PreserveAspectFit
+ anchors.fill: parent
+ anchors.centerIn: parent
+ scale: 1
+ opacity: 0.7
+ z: 0
+ }
+
+ Image {
+ id: background2
+ source: "./assets/Ellipse 1.svg"
+ sourceSize.width: width
+ sourceSize.height: width
+ anchors.fill: parent
+ anchors.centerIn: parent
+ fillMode: Image.PreserveAspectFit
+ scale: 1
+ opacity: 0.7
+ z: 1
+ }
+
+ Canvas {
+ id: canvas
+ anchors.fill: parent
+ antialiasing: true
+ property real degree: 0
+
+ onDegreeChanged: requestPaint()
+
+ onPaint: {
+ var ctx = getContext("2d")
+ var center = Qt.point(width / 2, height / 2)
+ var side = Math.min(width, height)
+ var radius = (side - side * 0.20) / 2
+ var startAngle = Math.PI * 3 / 4
+ var fullAngle = Math.PI * 3 / 2
+ var progressAngle = startAngle + (degree / 270) * fullAngle
+
+ ctx.reset()
+ ctx.lineCap = 'round'
+
+ ctx.lineWidth = side * 0.1
+ ctx.beginPath()
+ ctx.arc(center.x, center.y, radius, startAngle, progressAngle)
+ ctx.strokeStyle = secondaryColor
+ ctx.stroke()
+
+ ctx.lineWidth = 20
+ ctx.beginPath()
+ ctx.arc(center.x, center.y, radius, startAngle, progressAngle)
+ ctx.strokeStyle = primaryColor
+ ctx.stroke()
+
+ // draw tick marks
+ ctx.lineWidth = 10
+ ctx.strokeStyle = '#FFFFFF'
+ ctx.beginPath()
+ var tickCount = 2; // Number of tick marks
+ for (var i = 0; i < tickCount; i++) {
+ var angle = startAngle + (i / (tickCount - 1)) * (progressAngle - startAngle)
+ var x1 = center.x + radius * Math.cos(angle)
+ var y1 = center.y + radius * Math.sin(angle)
+ var x2 = center.x + (radius - 20) * Math.cos(angle)
+ var y2 = center.y + (radius - 20) * Math.sin(angle)
+ ctx.moveTo(x1, y1)
+ ctx.lineTo(x2, y2)
+ }
+ ctx.stroke()
+ }
+ }
+
+ Text {
+ id: gaugeText
+ anchors.centerIn: parent
+ text: "0"
+ font.pixelSize: 0.2 * Math.min(root.width, root.height)
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Text {
+ id: gaugeUnit
+ anchors.top: gaugeText.bottom
+ anchors.horizontalCenter: gaugeText.horizontalCenter
+
+ text: unit
+ font.pixelSize: 18
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Behavior on value {
+ NumberAnimation { duration: animationDuration }
+ }
+
+ onValueChanged: updateGaugeValue(value)
+
+ function updateGaugeValue(value) {
+ canvas.degree = value * 270
+ gaugeText.text = (value * (maxValue - minValue) + minValue).toFixed(0)
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+
+ property bool isDragging: false
+ property real initialValue: 0
+
+ onEntered: cursorShape = Qt.PointingHandCursor
+ onPressed: {
+ isDragging = true
+ initialValue = root.value
+ }
+ onReleased: isDragging = false
+
+ onMouseXChanged: updateDragValue(mouse.x, mouse.y)
+ onMouseYChanged: updateDragValue(mouse.x, mouse.y)
+
+ function updateDragValue(x, y) {
+ if (!isDragging) return
+
+ var centerX = width / 2
+ var centerY = height / 2
+ var dx = x - centerX
+ var dy = centerY - y // Note: y-axis is inverted
+ var angle = Math.atan2(dy, dx) * (180 / Math.PI)
+
+ // Convert angle to gauge value (0 to 1)
+ var gaugeValue = (angle + 135) / 270 // Adjust based on your gauge's start angle
+ gaugeValue = Math.max(0, Math.min(gaugeValue, 1)) // Clamp value
+
+ root.value = gaugeValue
+ }
+ }
+}
diff --git a/QMLWidgets/Full_Gauge/SpeedGauge.qml b/QMLWidgets/Full_Gauge/SpeedGauge.qml new file mode 100644 index 0000000..263e7f1 --- /dev/null +++ b/QMLWidgets/Full_Gauge/SpeedGauge.qml @@ -0,0 +1,202 @@ +import QtQuick 2.9
+
+Item {
+ id: root
+ width: 400
+ height: 400
+
+ property real value: 0
+ property real minValue: 0
+ property real maxValue: 240
+ property string unit: "Km/h"
+
+ property color primaryColor: "#16CCBA"
+ property color secondaryColor: "#00000000"
+ property int animationDuration: 500
+ property real startAngle: Math.PI * 3 / 4
+ property real fullAngle: Math.PI * 3 / 2
+
+ property real gaugeRadius: 0
+ property real tickLength: 0
+
+ Component.onCompleted: {
+ calculateGeometry();
+ }
+
+ onWidthChanged: calculateGeometry()
+ onHeightChanged: calculateGeometry()
+
+ function calculateGeometry() {
+ const side = Math.min(width, height);
+ gaugeRadius = (side - side * 0.20) / 2;
+ tickLength = gaugeRadius * 0.05;
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#041F2B"
+ z: -1
+ }
+
+ Image {
+ id: background1
+ source: "./assets/Ellipse 5.svg"
+ rotation: 180
+ sourceSize.width: width
+ sourceSize.height: width
+ fillMode: Image.PreserveAspectFit
+ anchors.fill: parent
+ scale: 1
+ opacity: 0.7
+ z: 0
+ }
+
+ Image {
+ id: background2
+ source: "./assets/Ellipse 1.svg"
+ sourceSize.width: width
+ sourceSize.height: width
+ fillMode: Image.PreserveAspectFit
+ anchors.fill: parent
+ scale: 1
+ opacity: 0.7
+ z: 1
+ }
+
+ Canvas {
+ id: canvas
+ anchors.fill: parent
+ antialiasing: true
+ property real degree: 0
+
+ onDegreeChanged: requestPaint()
+
+ onPaint: {
+ var ctx = getContext("2d");
+ var center = Qt.point(width / 2, height / 2);
+
+ ctx.reset();
+ ctx.lineCap = 'round';
+
+ drawBackground(ctx, center);
+ drawProgress(ctx, center, degree);
+ drawTicks(ctx, center);
+ drawProgressTick(ctx, center, degree);
+ }
+
+ function drawBackground(ctx, center) {
+ ctx.lineWidth = gaugeRadius * 0.1;
+ ctx.beginPath();
+ ctx.arc(center.x, center.y, gaugeRadius, startAngle, startAngle + fullAngle);
+ ctx.strokeStyle = secondaryColor;
+ ctx.stroke();
+ }
+
+ function drawProgress(ctx, center, progress) {
+ ctx.lineWidth = 20;
+ ctx.beginPath();
+ ctx.arc(center.x, center.y, gaugeRadius, startAngle, startAngle + (progress / 270) * fullAngle);
+ ctx.strokeStyle = primaryColor;
+ ctx.stroke();
+ }
+
+ function drawTicks(ctx, center) {
+ ctx.lineWidth = tickLength * 2
+ ctx.strokeStyle = '#FFFFFF'
+ ctx.beginPath()
+ const tickCount = 2
+ for (let i = 0; i < tickCount; i++) {
+ const angle = startAngle + (i / (tickCount - 1)) * fullAngle
+ const x1 = center.x + gaugeRadius * Math.cos(angle)
+ const y1 = center.y + gaugeRadius * Math.sin(angle)
+ const x2 = center.x + (gaugeRadius - tickLength) * Math.cos(angle)
+ const y2 = center.y + (gaugeRadius - tickLength) * Math.sin(angle)
+ ctx.moveTo(x1, y1)
+ ctx.lineTo(x2, y2)
+ }
+ ctx.stroke();
+ }
+
+ function drawProgressTick(ctx, center, progress) {
+
+ ctx.lineWidth = tickLength * 3
+ ctx.strokeStyle = '#FFFFFF'
+ ctx.beginPath()
+
+ const progressAngle = startAngle + (progress / 270) * fullAngle
+ const x1 = center.x + gaugeRadius * Math.cos(progressAngle)
+ const y1 = center.y + gaugeRadius * Math.sin(progressAngle)
+ const x2 = center.x + (gaugeRadius - tickLength * 1.5) * Math.cos(progressAngle)
+ const y2 = center.y + (gaugeRadius - tickLength * 1.5) * Math.sin(progressAngle)
+
+ ctx.moveTo(x1, y1)
+ ctx.lineTo(x2, y2)
+ ctx.stroke()
+ }
+ }
+
+ Text {
+ id: gaugeText
+ anchors.centerIn: parent
+ text: "0"
+ font.pixelSize: 0.2 * Math.min(root.width, root.height)
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Text {
+ id: gaugeUnit
+ anchors.top: gaugeText.bottom
+ anchors.horizontalCenter: gaugeText.horizontalCenter
+ text: unit
+ font.pixelSize: 18
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Behavior on value {
+ NumberAnimation { duration: animationDuration }
+ }
+
+ onValueChanged: updateGaugeValue(value)
+
+ function updateGaugeValue(value) {
+ canvas.degree = value * 270
+ gaugeText.text = (value * (maxValue - minValue) + minValue).toFixed(0)
+ }
+
+ MouseArea {
+ id: dragArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ property bool isDragging: false
+ property real initialValue: 0
+
+ onEntered: cursorShape = Qt.PointingHandCursor
+ onPressed: {
+ isDragging = true
+ initialValue = root.value
+ }
+ onReleased: isDragging = false
+
+ onMouseXChanged: updateDragValue(mouse.x, mouse.y)
+ onMouseYChanged: updateDragValue(mouse.x, mouse.y)
+
+ function updateDragValue(x, y) {
+ if (!isDragging) return
+
+ const centerX = width / 2
+ const centerY = height / 2
+ const dx = x - centerX
+ const dy = centerY - y // Note: y-axis is inverted
+ const angle = Math.atan2(dy, dx) * (180 / Math.PI)
+
+ // Convert angle to gauge value (0 to 1)
+ let gaugeValue = (angle + 135) / 270
+ gaugeValue = Math.max(0, Math.min(gaugeValue, 1)) // Clamp value
+
+ root.value = gaugeValue
+ }
+ }
+}
diff --git a/QMLWidgets/Full_Gauge/assets/Ellipse 1.svg b/QMLWidgets/Full_Gauge/assets/Ellipse 1.svg new file mode 100644 index 0000000..c2666d9 --- /dev/null +++ b/QMLWidgets/Full_Gauge/assets/Ellipse 1.svg @@ -0,0 +1,11 @@ +<svg width="400" height="400" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg"> +<circle cx="200" cy="200" r="187.5" stroke="url(#paint0_linear_1_121)" stroke-width="25" stroke-dasharray="5 5"/> +<defs> +<linearGradient id="paint0_linear_1_121" x1="-4" y1="196" x2="407.5" y2="196" gradientUnits="userSpaceOnUse"> +<stop stop-color="#9EFFD6"/> +<stop offset="0.333683" stop-color="#E6FFB0" stop-opacity="0"/> +<stop offset="0.675444" stop-color="#E6FFB0" stop-opacity="0"/> +<stop offset="1" stop-color="#9EFFD6"/> +</linearGradient> +</defs> +</svg> diff --git a/QMLWidgets/Full_Gauge/assets/Ellipse 5.svg b/QMLWidgets/Full_Gauge/assets/Ellipse 5.svg new file mode 100644 index 0000000..a4a07a2 --- /dev/null +++ b/QMLWidgets/Full_Gauge/assets/Ellipse 5.svg @@ -0,0 +1,24 @@ +<svg width="203" height="200" viewBox="0 0 203 200" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_ii_109_7)"> +<circle cx="101.5" cy="98.5" r="101.5" fill="#09111E"/> +</g> +<circle cx="101.5" cy="98.5" r="101" stroke="#A6FFFA"/> +<defs> +<filter id="filter0_ii_109_7" x="0" y="-13" width="203" height="223" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="10"/> +<feGaussianBlur stdDeviation="10"/> +<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.625 0 0 0 0 0.99537 0 0 0 0 1 0 0 0 0.6 0"/> +<feBlend mode="normal" in2="shape" result="effect1_innerShadow_109_7"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="-10"/> +<feGaussianBlur stdDeviation="10"/> +<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.623529 0 0 0 0 0.996078 0 0 0 0 1 0 0 0 0.6 0"/> +<feBlend mode="normal" in2="effect1_innerShadow_109_7" result="effect2_innerShadow_109_7"/> +</filter> +</defs> +</svg> diff --git a/QMLWidgets/Half_Gauge/CoolantGauge.qml b/QMLWidgets/Half_Gauge/CoolantGauge.qml new file mode 100644 index 0000000..6e1d583 --- /dev/null +++ b/QMLWidgets/Half_Gauge/CoolantGauge.qml @@ -0,0 +1,150 @@ +import QtQuick 2.9
+
+Item {
+ id: root
+ width: 200
+ height: 200
+
+ property real value: 80
+ property real minValue: 0
+ property real maxValue: 120
+ property string unit: "°C"
+
+ property color primaryColor: "#16CCBA"
+ property color secondaryColor: "#00000000"
+ property int animationDuration: 500
+ property real startAngle: 0
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#041F2B"
+ z: -1
+ }
+
+ Canvas {
+ id: canvas
+ anchors.fill: parent
+ antialiasing: true
+ property real degree: 0
+
+ onDegreeChanged: requestPaint()
+
+ onPaint: {
+ var ctx = getContext("2d")
+ var center = Qt.point(width / 2, height / 2)
+ var side = Math.min(width, height)
+ var radius = (side - side * 0.25) / 2
+ var startAngle = Math.PI * 2 / 3
+ var fullAngle = Math.PI * 2 / 3
+ var progressAngle = startAngle + (degree / 270) * fullAngle
+
+ ctx.reset()
+ ctx.lineCap = 'square'
+
+ // background arc
+ ctx.lineWidth = 25
+ ctx.beginPath()
+ ctx.arc(center.x, center.y, radius, startAngle, startAngle + fullAngle)
+ ctx.strokeStyle = '#000000'
+ ctx.stroke()
+
+ // fill arc
+ ctx.lineWidth = 15
+ ctx.beginPath()
+ ctx.arc(center.x, center.y, radius, startAngle, progressAngle)
+ ctx.strokeStyle = primaryColor
+ ctx.stroke()
+
+ // draw tick marks
+ ctx.lineWidth = 5
+ ctx.strokeStyle = '#FFFFFF'
+ ctx.beginPath()
+ var tickCount = 2; // Number of tick marks
+ for (var i = 0; i < tickCount; i++) {
+ var angle = startAngle + (i / (tickCount - 1)) * (progressAngle - startAngle)
+ var x1 = center.x + radius * Math.cos(angle)
+ var y1 = center.y + radius * Math.sin(angle)
+ var x2 = center.x + (radius - 10) * Math.cos(angle)
+ var y2 = center.y + (radius - 10) * Math.sin(angle)
+ ctx.moveTo(x1, y1)
+ ctx.lineTo(x2, y2)
+ }
+ ctx.stroke()
+ }
+ }
+
+ Text {
+ id: gaugeText
+ anchors.centerIn: parent
+ text: "0"
+ font.pixelSize: 0.3 * Math.min(root.width, root.height)
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Text {
+ id: gaugePercentage
+ anchors.verticalCenter: gaugeText.verticalCenter
+ anchors.left: gaugeText.right
+ text: "%"
+ font.pixelSize: 0.15 * Math.min(root.width, root.height)
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Text {
+ id: gaugeUnit
+ anchors.top: gaugeText.bottom
+ anchors.horizontalCenter: gaugeText.horizontalCenter
+
+ text: unit
+ font.pixelSize: 18
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Behavior on value {
+ NumberAnimation { duration: animationDuration }
+ }
+
+ onValueChanged: updateGaugeValue(value)
+
+ function updateGaugeValue(value) {
+ canvas.degree = value * 270
+ gaugeText.text = (value * (maxValue - minValue) + minValue).toFixed(0)
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+
+ property bool isDragging: false
+ property real initialValue: 0
+
+ onEntered: cursorShape = Qt.PointingHandCursor
+ onPressed: {
+ isDragging = true
+ initialValue = root.value
+ }
+ onReleased: isDragging = false
+
+ onMouseXChanged: updateDragValue(mouse.x, mouse.y)
+ onMouseYChanged: updateDragValue(mouse.x, mouse.y)
+
+ function updateDragValue(x, y) {
+ if (!isDragging) return
+
+ var centerX = width / 2
+ var centerY = height / 2
+ var dx = x - centerX
+ var dy = centerY - y // Note: y-axis is inverted
+ var angle = Math.atan2(dy, dx) * (180 / Math.PI)
+
+ // Convert angle to gauge value (0 to 1)
+ var gaugeValue = (angle + 135) / 270; // Adjust based on your gauge's start angle
+ gaugeValue = Math.max(0, Math.min(gaugeValue, 1)); // Clamp value
+
+ root.value = gaugeValue;
+ }
+ }
+}
diff --git a/QMLWidgets/Half_Gauge/FuelGauge.qml b/QMLWidgets/Half_Gauge/FuelGauge.qml new file mode 100644 index 0000000..21ac4cd --- /dev/null +++ b/QMLWidgets/Half_Gauge/FuelGauge.qml @@ -0,0 +1,158 @@ +import QtQuick 2.9
+
+Item {
+ id: root
+ width: 200
+ height: 200
+
+ property real value: 80
+ property real minValue: 0
+ property real maxValue: 100
+ property string unit: "NA"
+
+ property color primaryColor: "#16CCBA"
+ property color secondaryColor: "#00000000"
+ property int animationDuration: 500
+ property real startAngle: 0
+
+ property var exposedFunction: updateGaugeUnit
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#041F2B"
+ z: -1
+ }
+
+ Canvas {
+ id: canvas
+ anchors.fill: parent
+ antialiasing: true
+ property real degree: 0
+
+ onDegreeChanged: requestPaint()
+
+ onPaint: {
+ var ctx = getContext("2d")
+ var center = Qt.point(width / 2, height / 2)
+ var side = Math.min(width, height)
+ var radius = (side - side * 0.25) / 2
+ var startAngle = Math.PI * 2 / 3
+ var fullAngle = Math.PI * 2 / 3
+ var progressAngle = startAngle + (degree / 270) * fullAngle
+
+ ctx.reset()
+ ctx.lineCap = 'square'
+
+ // background arc
+ ctx.lineWidth = 25
+ ctx.beginPath()
+ ctx.arc(center.x, center.y, radius, startAngle, startAngle + fullAngle)
+ ctx.strokeStyle = '#000000'
+ ctx.stroke()
+
+ // fill arc
+ ctx.lineWidth = 15
+ ctx.beginPath()
+ ctx.arc(center.x, center.y, radius, startAngle, progressAngle)
+ ctx.strokeStyle = primaryColor
+ ctx.stroke()
+
+ // draw tick marks
+ ctx.lineWidth = 5
+ ctx.strokeStyle = '#FFFFFF'
+ ctx.beginPath()
+ var tickCount = 2; // Number of tick marks
+ for (var i = 0; i < tickCount; i++) {
+ var angle = startAngle + (i / (tickCount - 1)) * (progressAngle - startAngle)
+ var x1 = center.x + radius * Math.cos(angle)
+ var y1 = center.y + radius * Math.sin(angle)
+ var x2 = center.x + (radius - 10) * Math.cos(angle)
+ var y2 = center.y + (radius - 10) * Math.sin(angle)
+ ctx.moveTo(x1, y1)
+ ctx.lineTo(x2, y2)
+ }
+ ctx.stroke()
+ }
+ }
+
+ Text {
+ id: gaugeText
+ anchors.centerIn: parent
+ text: "0"
+ font.pixelSize: 0.3 * Math.min(root.width, root.height)
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Text {
+ id: gaugePercentage
+ // anchor this to the right of the gaugeText such that their baseline is aligned
+
+ anchors.verticalCenter: gaugeText.verticalCenter
+ anchors.left: gaugeText.right
+ text: "%"
+ font.pixelSize: 0.15 * Math.min(root.width, root.height)
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Text {
+ id: gaugeUnit
+ anchors.top: gaugeText.bottom
+ anchors.horizontalCenter: gaugeText.horizontalCenter
+
+ text: unit
+ font.pixelSize: 18
+ font.bold: true
+ color: "#FFFFFF"
+ }
+
+ Behavior on value {
+ NumberAnimation { duration: animationDuration }
+ }
+
+ onValueChanged: updateGaugeValue(value)
+
+ function updateGaugeValue(value) {
+ canvas.degree = value * 270
+ gaugeText.text = (value * (maxValue - minValue) + minValue).toFixed(0)
+ }
+
+ function updateGaugeUnit() {
+ gaugeUnit.text = unit
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ hoverEnabled: true
+
+ property bool isDragging: false
+ property real initialValue: 0
+
+ onEntered: cursorShape = Qt.PointingHandCursor
+ onPressed: {
+ isDragging = true
+ initialValue = root.value
+ }
+ onReleased: isDragging = false
+
+ onMouseXChanged: updateDragValue(mouse.x, mouse.y)
+ onMouseYChanged: updateDragValue(mouse.x, mouse.y)
+
+ function updateDragValue(x, y) {
+ if (!isDragging) return
+
+ var centerX = width / 2
+ var centerY = height / 2
+ var dx = x - centerX
+ var dy = centerY - y // Note: y-axis is inverted
+ var angle = Math.atan2(dy, dx) * (180 / Math.PI)
+
+ // Convert angle to gauge value (0 to 1)
+ var gaugeValue = (angle + 135) / 270; // Adjust based on your gauge's start angle
+ gaugeValue = Math.max(0, Math.min(gaugeValue, 1)); // Clamp value
+
+ root.value = gaugeValue;
+ }
+ }
+}
diff --git a/Scripts/record_playback.py b/Scripts/record_playback.py index e518356..5d3956e 100644 --- a/Scripts/record_playback.py +++ b/Scripts/record_playback.py @@ -139,3 +139,4 @@ def main(): if __name__ == "__main__": main() + diff --git a/Widgets/ICPage.py b/Widgets/ICPage.py index 213e74c..e3d4ddf 100644 --- a/Widgets/ICPage.py +++ b/Widgets/ICPage.py @@ -10,7 +10,8 @@ from PyQt6 import uic, QtCore, QtWidgets from PyQt6.QtWidgets import QApplication from PyQt6.QtGui import QIcon, QPixmap, QPainter from PyQt6.QtCore import QObject, pyqtSignal -from PyQt6.QtWidgets import QWidget +from PyQt6.QtWidgets import QWidget, QFrame +from PyQt6.QtQuickWidgets import QQuickWidget import threading current_dir = os.path.dirname(os.path.abspath(__file__)) @@ -31,6 +32,41 @@ from Scripts.record_playback import CAN_playback import res_rc from Widgets.animatedToggle import AnimatedToggle +def Gauge(gaugeType): + """QWidget + This function creates a full gauge widget with the specified maximum value, current value, and unit. + + Args: + - maxValue: The maximum value of the gauge. + - value: The current value of the gauge. + - unit: The unit of the gauge. + + Returns: + - A QQuickWidget object representing the full gauge widget. + """ + + RPM_GaugeQML = os.path.join(current_dir, "../QMLWidgets/Full_Gauge/RPMGauge.qml") + Speed_GaugeQML = os.path.join(current_dir, "../QMLWidgets/Full_Gauge/SpeedGauge.qml") + Fuel_GaugeQML = os.path.join(current_dir, "../QMLWidgets/Half_Gauge/FuelGauge.qml") + Coolant_GaugeQML = os.path.join(current_dir, "../QMLWidgets/Half_Gauge/CoolantGauge.qml") + + gauge = QQuickWidget() + if gaugeType == "RPM": + gauge.setSource(QtCore.QUrl(RPM_GaugeQML)) + + elif gaugeType == "Speed": + gauge.setSource(QtCore.QUrl(Speed_GaugeQML)) + + elif gaugeType == "Fuel": + gauge.setSource(QtCore.QUrl(Fuel_GaugeQML)) + + elif gaugeType == "Coolant": + gauge.setSource(QtCore.QUrl(Coolant_GaugeQML)) + + gauge.setResizeMode(QQuickWidget.ResizeMode.SizeRootObjectToView) + + return gauge + class IC_Paths(): def __init__(self): self.speed = "Vehicle.Speed" @@ -42,7 +78,6 @@ class IC_Paths(): self.coolantTemp = "Vehicle.Powertrain.CombustionEngine.ECT" self.selectedGear = "Vehicle.Powertrain.Transmission.SelectedGear" - class ICWidget(Base, Form): """ This class represents the ICWidget which is a widget for the AGL Demo Control Panel. @@ -68,7 +103,9 @@ class ICWidget(Base, Form): header_frame = self.findChild(QWidget, "header_frame") layout = header_frame.layout() - self.IC_Frame = self.findChild(QWidget, "frame_1") + self.Frame_1 = self.findChild(QWidget, "frame_1") + self.Fuel_Gauge_Frame = self.findChild(QFrame, "fuel_gauge_frame") + self.Coolant_Gauge_Frame = self.findChild(QFrame, "coolant_gauge_frame") self.Script_toggle = AnimatedToggle() @@ -93,23 +130,41 @@ class ICWidget(Base, Form): self.driveGroupBtns.buttonClicked.connect(self.driveBtnClicked) - self.Speed_slider.valueChanged.connect(self.update_Speed_monitor) + Speed_Gauge_Placeholder = self.findChild(QWidget, "Speed_Gauge_Placeholder") + self.Speed_Gauge = Gauge("Speed") + self.Frame_1.layout().replaceWidget(Speed_Gauge_Placeholder, self.Speed_Gauge) + + self.Speed_slider.valueChanged.connect(self.update_Speed_gauge) self.Speed_slider.setMinimum(0) self.Speed_slider.setMaximum(240) + RPM_Gauge_Placeholder = self.findChild(QWidget, "RPM_Gauge_Placeholder") + self.RPM_Gauge = Gauge("RPM") + self.Frame_1.layout().replaceWidget(RPM_Gauge_Placeholder, self.RPM_Gauge) + self.RPM_slider.valueChanged.connect(self.update_RPM_monitor) self.RPM_slider.setMinimum(0) self.RPM_slider.setMaximum(8000) + fuel_Gauge_Placeholder = self.findChild(QWidget, "fuel_Gauge_Placeholder") + self.Fuel_Gauge = Gauge("Fuel") + self.Fuel_Gauge_Frame.layout().replaceWidget(fuel_Gauge_Placeholder, self.Fuel_Gauge) + + coolant_Gauge_Placeholder = self.findChild(QWidget, "coolant_Gauge_Placeholder") + self.Coolant_Gauge = Gauge("Coolant") + self.Coolant_Gauge_Frame.layout().replaceWidget(coolant_Gauge_Placeholder, self.Coolant_Gauge) + + self.mousePressEvent = lambda event: print("Mouse Pressed") + self.mouseReleaseEvent = lambda event: print("Mouse Released") + + self.Coolant_Gauge.mousePressEvent = self.mousePressEvent + self.Coolant_Gauge.mouseReleaseEvent = self.mouseReleaseEvent + self.coolantTemp_slider.valueChanged.connect( self.update_coolantTemp_monitor) self.fuelLevel_slider.valueChanged.connect( self.update_fuelLevel_monitor) - self.accelerationBtn.pressed.connect(self.accelerationBtnPressed) - self.accelerationBtn.released.connect(self.accelerationBtnReleased) - - # make both buttons checkable self.Script_toggle.clicked.connect(self.handle_Script_toggle) self.leftIndicatorBtn.setCheckable(True) self.rightIndicatorBtn.setCheckable(True) @@ -125,12 +180,13 @@ class ICWidget(Base, Form): def set_Vehicle_RPM(self, rpm): self.RPM_slider.setValue(rpm) - def update_Speed_monitor(self): + def update_Speed_gauge(self): """ Updates the speed monitor with the current speed value. """ speed = int(self.Speed_slider.value()) - self.Speed_monitor.display(speed) + speed = speed / 240 + self.Speed_Gauge.rootObject().setProperty('value', speed) if not self.simulator_running: try: self.kuksa_client.set(self.IC.speed, str(speed), 'value') @@ -142,7 +198,8 @@ class ICWidget(Base, Form): Updates the RPM monitor with the current RPM value. """ rpm = int(self.RPM_slider.value()) - self.RPM_monitor.display(rpm) + rpm = rpm / 8000 + self.RPM_Gauge.rootObject().setProperty('value', rpm) if not self.simulator_running: try: self.kuksa_client.set(self.IC.engineRPM, str(rpm), 'value') @@ -154,6 +211,7 @@ class ICWidget(Base, Form): Updates the coolant temperature monitor with the current coolant temperature value. """ coolantTemp = int(self.coolantTemp_slider.value()) + self.Coolant_Gauge.rootObject().setProperty('value', coolantTemp/100) try: self.kuksa_client.set( self.IC.coolantTemp, str(coolantTemp), 'value') @@ -165,6 +223,8 @@ class ICWidget(Base, Form): Updates the fuel level monitor with the current fuel level value. """ fuelLevel = int(self.fuelLevel_slider.value()) + self.Fuel_Gauge.rootObject().setProperty('value', fuelLevel/100) + print(self.Fuel_Gauge.rootObject().property('value')) try: self.kuksa_client.set(self.IC.fuelLevel, str(fuelLevel)) except Exception as e: @@ -279,7 +339,7 @@ class ICWidget(Base, Form): if self.Script_toggle.isChecked(): self.Speed_slider.setEnabled(False) self.RPM_slider.setEnabled(False) - self.accelerationBtn.setEnabled(False) + # self.accelerationBtn.setEnabled(False) for button in self.driveGroupBtns.buttons(): button.setEnabled(False) self.set_Vehicle_RPM(1000) @@ -291,7 +351,7 @@ class ICWidget(Base, Form): self.simulator_running = False self.Speed_slider.setEnabled(True) self.RPM_slider.setEnabled(True) - self.accelerationBtn.setEnabled(True) + # self.accelerationBtn.setEnabled(True) for button in self.driveGroupBtns.buttons(): button.setEnabled(True) @@ -321,7 +381,7 @@ class ICWidget(Base, Form): self.Speed_slider.setValue(self.current_speed) self.RPM_slider.setValue(self.current_rpm) - self.update_Speed_monitor() + self.update_Speed_gauge() self.update_RPM_monitor() def driveBtnClicked(self): @@ -336,7 +396,7 @@ class ICWidget(Base, Form): if checked_button in gear_mapping: gear_value = gear_mapping[checked_button] - self.accelerationBtn.setEnabled(True) + # self.accelerationBtn.setEnabled(True) self.Speed_slider.setEnabled(checked_button != self.neutralBtn) self.RPM_slider.setEnabled(True) try: @@ -346,7 +406,6 @@ class ICWidget(Base, Form): else: print("Unknown button checked!") - class AccelerationFns(): def calculate_speed(time, acceleration) -> int: # acceleration = 60 / 5 # acceleration from 0 to 60 in 5 seconds diff --git a/Widgets/Keypad.py b/Widgets/Keypad.py new file mode 100644 index 0000000..ad0c17e --- /dev/null +++ b/Widgets/Keypad.py @@ -0,0 +1,53 @@ +import os +import sys +from PyQt6 import uic +from PyQt6.QtWidgets import QApplication, QWidget, QPushButton +import requests +from urllib.parse import urljoin + +current_dir = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.dirname(current_dir)) + +Form, Base = uic.loadUiType(os.path.join(current_dir, "../ui/Keypad.ui")) + +import res_rc + +class KeypadWidget(Base, Form): + def __init__(self, parent=None): + super(self.__class__, self).__init__(parent) + self.setupUi(self) + self.host = "localhost" + self.port = 8080 + + # Mapping of keys to API endpoints + self.key_endpoints = { + "Key_1": "/cgi-bin/flutter.cgi", + "Key_2": "/cgi-bin/qt.cgi", + "Key_3": "/cgi-bin/momi.cgi", + "Key_4": "/cgi-bin/bomb.cgi", + "Key_5": "", # This key won't do anything + } + + # Connect all keys to the same slot + for key_name in self.key_endpoints.keys(): + key_button = self.findChild(QPushButton, key_name) + key_button.clicked.connect(lambda _, x=key_name: self.trigger_api(x)) + + def trigger_api(self, key_name): + endpoint = self.key_endpoints[key_name] + if endpoint: + url = f"http://{self.host}:{self.port}{endpoint}" + try: + response = requests.get(url, timeout=5) + response.raise_for_status() + print(f"API triggered successfully: {url}") + except requests.exceptions.RequestException as e: + print(f"Error triggering API: {str(e)}") + else: + print("No action defined for this key.") + +if __name__ == '__main__': + app = QApplication(sys.argv) + w = KeypadWidget() + w.show() + sys.exit(app.exec()) diff --git a/requirements.txt b/requirements.txt index 490e913..ab78645 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,6 @@ PySide6==6.7.1 PySide6_Addons==6.7.1 PySide6_Essentials==6.7.1 kuksa-client==0.4.0 -python-can>=4.2.2
\ No newline at end of file +python-can>=4.2.2 +requests +rich
\ No newline at end of file @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>920</width> - <height>800</height> + <width>1200</width> + <height>880</height> </rect> </property> <property name="windowTitle"> @@ -166,33 +166,13 @@ QLCDNumber { </property> <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0" rowspan="2"> - <spacer name="horizontalSpacer_12"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="2" rowspan="2"> - <spacer name="horizontalSpacer_13"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="1" rowspan="2"> <widget class="QFrame" name="frame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> <width>500</width> @@ -206,84 +186,10 @@ QLCDNumber { <enum>QFrame::Raised</enum> </property> <layout class="QGridLayout" name="gridLayout_4"> - <item row="0" column="0"> - <widget class="QFrame" name="header_frame"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>50</height> - </size> - </property> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QFrame" name="frame_6"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="label"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <family>Open Sans Extrabold</family> - <pointsize>18</pointsize> - <weight>75</weight> - <italic>true</italic> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Instrument Cluster</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QLabel" name="label_6"> - <property name="font"> - <font> - <pointsize>18</pointsize> - <weight>75</weight> - <italic>true</italic> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Demo Mode</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="demoToggle"> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="0"> - <widget class="QFrame" name="frame_3"> + <item row="2" column="0"> + <widget class="QFrame" name="frame_1"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -297,7 +203,7 @@ QLCDNumber { <property name="maximumSize"> <size> <width>16777215</width> - <height>150</height> + <height>16777215</height> </size> </property> <property name="frameShape"> @@ -306,150 +212,83 @@ QLCDNumber { <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="1" column="4"> - <widget class="QPushButton" name="rightIndicatorBtn"> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../assets/res.qrc"> - <normaloff>:/Images/Images/right.png</normaloff>:/Images/Images/right.png</iconset> + <layout class="QGridLayout" name="gridLayout"> + <item row="3" column="3" alignment="Qt::AlignBottom"> + <widget class="QSlider" name="Speed_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="iconSize"> + <property name="minimumSize"> <size> - <width>60</width> + <width>0</width> <height>60</height> </size> </property> - </widget> - </item> - <item row="1" column="1"> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> + <property name="maximum"> + <number>240</number> </property> - </spacer> - </item> - <item row="1" column="3"> - <spacer name="horizontalSpacer_4"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> + <property name="tickPosition"> + <enum>QSlider::NoTicks</enum> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> + <property name="tickInterval"> + <number>0</number> </property> - </spacer> + </widget> </item> - <item row="1" column="0"> - <widget class="QPushButton" name="leftIndicatorBtn"> - <property name="acceptDrops"> - <bool>false</bool> + <item row="4" column="3" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="label_4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="autoFillBackground"> - <bool>false</bool> + <property name="font"> + <font> + <family>Open Sans</family> + <weight>75</weight> + <italic>true</italic> + <bold>true</bold> + </font> </property> <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../assets/res.qrc"> - <normaloff>:/Images/Images/left.png</normaloff>:/Images/Images/left.png</iconset> - </property> - <property name="iconSize"> - <size> - <width>60</width> - <height>60</height> - </size> - </property> - <property name="checkable"> - <bool>false</bool> - </property> - <property name="checked"> - <bool>false</bool> + <string>Speed (Kmph)</string> </property> </widget> </item> - <item row="1" column="2"> - <widget class="QPushButton" name="hazardBtn"> - <property name="text"> - <string/> - </property> - <property name="icon"> - <iconset resource="../assets/res.qrc"> - <normaloff>:/Images/Images/hazard.png</normaloff>:/Images/Images/hazard.png</iconset> + <item row="2" column="3"> + <widget class="QWidget" name="Speed_Gauge_Placeholder" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="iconSize"> - <size> - <width>60</width> - <height>60</height> - </size> + <property name="autoFillBackground"> + <bool>false</bool> </property> </widget> </item> - </layout> - </widget> - </item> - <item row="2" column="0"> - <spacer name="verticalSpacer_4"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="3" column="0"> - <widget class="QFrame" name="frame_1"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>200</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>150</height> - </size> - </property> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="4" column="8" alignment="Qt::AlignHCenter"> + <item row="4" column="4" alignment="Qt::AlignHCenter|Qt::AlignTop"> <widget class="QLabel" name="label_5"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="font"> <font> <family>Open Sans</family> @@ -463,50 +302,191 @@ QLCDNumber { </property> </widget> </item> - <item row="1" column="5" rowspan="2" colspan="2"> - <widget class="QLCDNumber" name="Speed_monitor"> + <item row="0" column="2" colspan="4"> + <spacer name="verticalSpacer_5"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>10</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="4"> + <widget class="QWidget" name="RPM_Gauge_Placeholder" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="3" column="4" alignment="Qt::AlignBottom"> + <widget class="QSlider" name="RPM_slider"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="font"> - <font> - <weight>50</weight> - <italic>false</italic> - <bold>false</bold> - </font> + <property name="minimumSize"> + <size> + <width>0</width> + <height>60</height> + </size> </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> + </widget> + </item> + <item row="1" column="2" colspan="3"> + <widget class="QFrame" name="frame_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="smallDecimalPoint"> - <bool>false</bool> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> </property> - <property name="digitCount"> - <number>3</number> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>150</height> + </size> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="4"> + <widget class="QPushButton" name="rightIndicatorBtn"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../assets/res.qrc"> + <normaloff>:/Images/Images/right.png</normaloff>:/Images/Images/right.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>60</width> + <height>60</height> + </size> + </property> + </widget> + </item> + <item row="1" column="1"> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="3"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <widget class="QPushButton" name="leftIndicatorBtn"> + <property name="acceptDrops"> + <bool>false</bool> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../assets/res.qrc"> + <normaloff>:/Images/Images/left.png</normaloff>:/Images/Images/left.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>60</width> + <height>60</height> + </size> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="hazardBtn"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../assets/res.qrc"> + <normaloff>:/Images/Images/hazard.png</normaloff>:/Images/Images/hazard.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>60</width> + <height>60</height> + </size> + </property> + </widget> + </item> + </layout> </widget> </item> - <item row="1" column="1" rowspan="4" colspan="2"> - <widget class="QFrame" name="frame_2"> + <item row="1" column="0" rowspan="4" colspan="2"> + <widget class="QFrame" name="coolant_gauge_frame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="spacing"> - <number>0</number> - </property> + <layout class="QGridLayout" name="gridLayout_5"> <property name="leftMargin"> <number>0</number> </property> @@ -519,8 +499,33 @@ QLCDNumber { <property name="bottomMargin"> <number>4</number> </property> - <item> + <item row="1" column="1"> + <widget class="QSlider" name="coolantTemp_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>60</width> + <height>0</height> + </size> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item row="1" column="0"> <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string/> </property> @@ -529,207 +534,51 @@ QLCDNumber { </property> </widget> </item> - <item> - <widget class="QSlider" name="coolantTemp_slider"> + <item row="0" column="0" colspan="2"> + <widget class="QWidget" name="coolant_Gauge_Placeholder" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> - <width>60</width> + <width>0</width> <height>0</height> </size> </property> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> </widget> </item> </layout> </widget> </item> - <item row="1" column="0" rowspan="4"> - <spacer name="horizontalSpacer_10"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>10</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="3" colspan="8"> - <spacer name="verticalSpacer_5"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>10</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="12" rowspan="4"> - <spacer name="horizontalSpacer_11"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>10</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="3" column="8"> - <widget class="QSlider" name="RPM_slider"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>60</height> - </size> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - </widget> - </item> - <item row="1" column="7" rowspan="4"> - <widget class="Line" name="line"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - </widget> - </item> - <item row="1" column="3" rowspan="4" colspan="2"> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="8" rowspan="2"> - <widget class="QLCDNumber" name="RPM_monitor"> + <item row="1" column="6" rowspan="4" alignment="Qt::AlignRight"> + <widget class="QFrame" name="fuel_gauge_frame"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="digitCount"> - <number>4</number> - </property> - <property name="segmentStyle"> - <enum>QLCDNumber::Flat</enum> - </property> - </widget> - </item> - <item row="4" column="5" alignment="Qt::AlignHCenter"> - <widget class="QLabel" name="label_4"> - <property name="font"> - <font> - <family>Open Sans</family> - <weight>75</weight> - <italic>true</italic> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Speed (Kmph)</string> - </property> - </widget> - </item> - <item row="3" column="5"> - <widget class="QSlider" name="Speed_slider"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>60</height> - </size> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="maximum"> - <number>240</number> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="tickPosition"> - <enum>QSlider::NoTicks</enum> - </property> - <property name="tickInterval"> - <number>0</number> - </property> - </widget> - </item> - <item row="1" column="9" rowspan="4"> - <spacer name="horizontalSpacer_6"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="11" rowspan="4"> - <widget class="QFrame" name="frame_5"> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <property name="spacing"> - <number>0</number> - </property> + <layout class="QGridLayout" name="gridLayout_6"> <property name="bottomMargin"> <number>4</number> </property> - <item> + <item row="1" column="0" alignment="Qt::AlignRight"> <widget class="QSlider" name="fuelLevel_slider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> <width>60</width> @@ -758,10 +607,10 @@ QLCDNumber { </property> </widget> </item> - <item> + <item row="1" column="1" alignment="Qt::AlignRight"> <widget class="QLabel" name="label_3"> <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> @@ -785,95 +634,94 @@ QLCDNumber { </property> </widget> </item> + <item row="0" column="0" colspan="2"> + <widget class="QWidget" name="fuel_Gauge_Placeholder" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </widget> + </item> </layout> </widget> </item> </layout> </widget> </item> - <item row="4" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> + <item row="0" column="0"> + <widget class="QFrame" name="header_frame"> + <property name="minimumSize"> <size> - <width>20</width> - <height>40</height> + <width>0</width> + <height>50</height> </size> </property> - </spacer> - </item> - <item row="5" column="0"> - <widget class="QFrame" name="frame_4"> <property name="frameShape"> <enum>QFrame::StyledPanel</enum> </property> <property name="frameShadow"> <enum>QFrame::Raised</enum> </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item alignment="Qt::AlignTop"> - <widget class="QPushButton" name="accelerationBtn"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QFrame" name="frame_6"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>80</height> - </size> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item alignment="Qt::AlignRight"> + <widget class="QLabel" name="label_6"> <property name="font"> <font> - <family>Open Sans</family> - <pointsize>16</pointsize> + <pointsize>18</pointsize> <weight>75</weight> <italic>true</italic> <bold>true</bold> </font> </property> <property name="text"> - <string>Accelerate</string> - </property> - <property name="icon"> - <iconset> - <normaloff>:/Misc_icons/Misc_icons/speed-up-fill.svg</normaloff>:/Misc_icons/Misc_icons/speed-up-fill.svg</iconset> + <string>Demo Mode</string> </property> - <property name="iconSize"> - <size> - <width>60</width> - <height>60</height> - </size> + </widget> + </item> + <item alignment="Qt::AlignRight"> + <widget class="QCheckBox" name="demoToggle"> + <property name="text"> + <string/> </property> </widget> </item> </layout> </widget> </item> - <item row="6" column="0"> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="7" column="0"> + <item row="4" column="0" alignment="Qt::AlignBottom"> <widget class="QFrame" name="gearSelector"> <property name="minimumSize"> <size> diff --git a/ui/Keypad.ui b/ui/Keypad.ui new file mode 100644 index 0000000..cda5e42 --- /dev/null +++ b/ui/Keypad.ui @@ -0,0 +1,316 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>HVAC</class> + <widget class="QWidget" name="HVAC"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>420</width> + <height>690</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <property name="styleSheet"> + <string notr="true">*{ + border: none; + background-color: transparent; + background: none; + padding: 0; + margin: 0; + color: #fff; +} + +#scrollAreaWidgetContents{ + background-color: #131313 ; /* black */ +} + +#centralwidget{ + background-color: #131313 ; /* black */ +} + +#centralwidget QPushButton{ + background-color: #6C6C85 ; /* pastel purple */ + padding: 5px 10px; + border-radius: 10px; +} + +#centralwidget QPushButton:pressed { + background-color: #4BD7D6 ; /* light blue */ +} + +#centralwidget QSlider::groove:horizontal { + border: 1px solid #6C6C85 ; /* pastel purple */ + height: 15px; + border-radius: 8px; +} + +#centralwidget QSlider::sub-page:horizontal { + background-color: #4BD7D6 ; /* light blue */ + height: 15px; + border-radius: 5px; +} + +#centralwidget QSlider::handle:horizontal { + background: qlineargradient(x1:0, y1:0, x2:1, y2:1, + stop:0 #eee, stop:1 #ccc); + border: 1px solid #777; + width: 20px; + margin-top: -2px; + margin-bottom: -2px; + border-radius: 8px; +} + +QSlider::sub-page:vertical { + background-color: #131313 ; /* black */ + height: 20px; + width: 28px; + margin: 2px; + border: 1px solid #6C6C85 ; /* pastel purple */ + border-radius: 8px; +} + +QSlider::groove:vertical { + border-radius: 8px; + width: 28px; + margin: 2px; + border: 1px solid #6C6C85 ; /* pastel purple */ + background-color: #4BD7D6 ; /* light blue */ +} +QSlider::groove:vertical:hover { + background-color: rgb(55, 62, 76); +} +QSlider::handle:vertical { + background-color: #d5d5d5; + height: 15px; + width: 20px; + border-radius: 5px; +} +QSlider::handle:vertical:hover { + background-color: #6C6C85 ; /* pastel purple */ +} +QSlider::handle:vertical:pressed { + background-color: #4BD7D6 ; /* light blue */ +} + + +QScrollBar:horizontal { + min-width: 240px; + height: 13px; + } + + QScrollBar:vertical { + min-height: 240px; + width: 13px; + } + + QScrollBar::groove { + background: 2A2827; /* dark grey */ + border-radius: 5px; + } + + QScrollBar::handle { + background: #4BD7D6 ; /* light blue */ + border-radius: 5px; + } + + QScrollBar::handle:horizontal { + width: 25px; + } + + QScrollBar::handle:vertical { + height: 25px; scrollAreaWidgetContents + } + +#leftControls{ + background: #041F2B ; /* dark blue */ + border-radius: 10px; +} + +#rightControls{ + background: #041F2B ; /* dark blue */ + border-radius: 10px; +} + + +/*============================================*/ + +QListWidget { + min-height: 150px; + max-height: 150px; + background-color: #131313 ; /* black */ + border: 1px solid #6C6C85 ; /* pastel purple */ + border-radius: 8px; +} + +QListWidget::item { + height: 50px; + width: 50px; + border-radius: 8px; + text-align: center; +} + +QListWidget::item:selected { + background-color: #4BD7D6 ; /* light blue */ + border-radius: 8px; +} + +QListWidget::item:selected:!active { + border-width: 0px; +} + +QListWidget::item:selected:active { + background-color: #4BD7D6 ; /* light blue */ +} + +QListWidget::item:selected:!focus { + color: black; + border-width: 0px; +} + +QListWidget::item:focus { + background-color: #6C6C85 ; /* pastel purple */ +} + +QListWidget::item:hover { + background-color: #6C6C85 ; /* pastel purple */ +} + +</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QFrame" name="centralwidget"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="1" column="0"> + <widget class="QFrame" name="frame_2"> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="2" column="1"> + <widget class="QPushButton" name="Key_2"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>:/Keypad_Images/keypad_icons/f2-unpressed.png</normaloff>:/Keypad_Images/keypad_icons/f2-unpressed.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="Key_3"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>:/Keypad_Images/keypad_icons/f3-unpressed.png</normaloff>:/Keypad_Images/keypad_icons/f3-unpressed.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QPushButton" name="Key_1"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>:/Keypad_Images/keypad_icons/f1-unpressed.png</normaloff>:/Keypad_Images/keypad_icons/f1-unpressed.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + </widget> + </item> + <item row="4" column="2"> + <widget class="QPushButton" name="Key_5"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>:/Keypad_Images/keypad_icons/f5-unpressed.png</normaloff>:/Keypad_Images/keypad_icons/f5-unpressed.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QPushButton" name="Key_4"> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset> + <normaloff>:/Keypad_Images/keypad_icons/f4-unpressed.png</normaloff>:/Keypad_Images/keypad_icons/f4-unpressed.png</iconset> + </property> + <property name="iconSize"> + <size> + <width>100</width> + <height>100</height> + </size> + </property> + </widget> + </item> + <item row="4" column="1"> + <spacer name="horizontalSpacer"> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item row="2" column="0"> + <spacer name="verticalSpacer"> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../assets/res.qrc"/> + </resources> + <connections/> +</ui> |