diff options
Diffstat (limited to 'Widgets')
-rw-r--r-- | Widgets/HVACPage.py | 115 | ||||
-rw-r--r-- | Widgets/ICPage.py | 106 | ||||
-rw-r--r-- | Widgets/Keypad.py | 3 | ||||
-rw-r--r-- | Widgets/TirePressure.py | 129 |
4 files changed, 264 insertions, 89 deletions
diff --git a/Widgets/HVACPage.py b/Widgets/HVACPage.py index d101e15..8371dfe 100644 --- a/Widgets/HVACPage.py +++ b/Widgets/HVACPage.py @@ -6,7 +6,11 @@ import os import sys from PyQt6 import uic -from PyQt6.QtWidgets import QApplication, QListWidget, QSlider, QPushButton +from PyQt6.QtWidgets import QApplication, QFrame, QSlider, QPushButton, QWidget +from PyQt6 import QtWidgets +from PyQt6.QtQuickWidgets import QQuickWidget +from PyQt6.QtQuick import QQuickItem +from PyQt6.QtCore import QUrl current_dir = os.path.dirname(os.path.abspath(__file__)) @@ -14,7 +18,6 @@ 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/HVAC.ui")) # ======================================== @@ -29,14 +32,22 @@ class HVAC_Paths(): self.rightTemp = "Vehicle.Cabin.HVAC.Station.Row1.Passenger.Temperature" self.rightFanSpeed = "Vehicle.Cabin.HVAC.Station.Row1.Passenger.FanSpeed" - # temperatureList contains values from 32 to 16 - self.temperatureList = [str(i) + "°C" for i in range(32, 15, -1)] +def TumblerWidget(): + """QWidget for controlling HVAC Temperature.""" + + TumblerQML = os.path.join(current_dir, "../QMLWidgets/Temp_Tumbler/TempTumbler.qml") + + TumblerWidget = QQuickWidget() + TumblerWidget.setSource(QUrl.fromLocalFile(TumblerQML)) + TumblerWidget.setResizeMode(QQuickWidget.ResizeMode.SizeRootObjectToView) + TumblerWidget.setSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum) + return TumblerWidget class HVACWidget(Base, Form): """ A widget for controlling HVAC settings. - + Inherits from Base and Form. """ @@ -52,40 +63,29 @@ class HVACWidget(Base, Form): self.setupUi(self) self.HVAC = HVAC_Paths() - self.kuksa_client = KuksaClient() - self.leftTempList = self.findChild(QListWidget, "leftTempList") - self.leftTempList.addItems(self.HVAC.temperatureList) - self.leftTempList.setCurrentRow(0) - self.leftTempList.itemClicked.connect(self.leftTempListClicked) - self.leftTempList.itemSelectionChanged.connect( - self.leftTempListClicked) - self.leftTempList.wheelEvent = lambda event: None - - self.rightTempList = self.findChild(QListWidget, "rightTempList") - self.rightTempList.addItems(self.HVAC.temperatureList) - self.rightTempList.setCurrentRow(0) - self.rightTempList.itemClicked.connect(self.rightTempListClicked) - self.rightTempList.itemSelectionChanged.connect( - self.rightTempListClicked) - self.rightTempList.wheelEvent = lambda event: None - - self.leftTempUp = self.findChild(QPushButton, "leftTempUp") - self.leftTempUp.clicked.connect( - lambda: self.leftTempList.setCurrentRow(self.leftTempList.currentRow() - 1)) - - self.leftTempDown = self.findChild(QPushButton, "leftTempDown") - self.leftTempDown.clicked.connect( - lambda: self.leftTempList.setCurrentRow(self.leftTempList.currentRow() + 1)) - - self.rightTempUp = self.findChild(QPushButton, "rightTempUp") - self.rightTempUp.clicked.connect( - lambda: self.rightTempList.setCurrentRow(self.rightTempList.currentRow() - 1)) - - self.rightTempDown = self.findChild(QPushButton, "rightTempDown") - self.rightTempDown.clicked.connect( - lambda: self.rightTempList.setCurrentRow(self.rightTempList.currentRow() + 1)) + leftFrame = self.findChild(QFrame, "leftFrame") + + # Create left temperature tumbler + self.LeftTempTumbler = TumblerWidget() + + # Connect the left tumbler signal to the handler + self.LeftTempTumbler.rootObject().valueChanged.connect(self.onLeftTempChanged) + + # Replace placeholder LeftTemp_Placeholder with the LeftTempTumbler widget + leftFrame.layout().replaceWidget(self.findChild(QWidget, "LeftTemp_Placeholder"), self.LeftTempTumbler) + + rightFrame = self.findChild(QFrame, "rightFrame") + + # Create right temperature tumbler + self.RightTempTumbler = TumblerWidget() + + # Connect the right tumbler signal to the handler + self.RightTempTumbler.rootObject().valueChanged.connect(self.onRightTempChanged) + + # Replace placeholder RightTemp_Placeholder with the RightTempTumbler widget + rightFrame.layout().replaceWidget(self.findChild(QWidget, "RightTemp_Placeholder"), self.RightTempTumbler) self.leftFanSpeed_slider = self.findChild( QSlider, "leftFanSpeed_slider") @@ -97,28 +97,27 @@ class HVACWidget(Base, Form): self.rightFanSpeed_slider.valueChanged.connect( self.rightFanSpeed_sliderChanged) - def leftTempListClicked(self): - """ - Handles the event when an item in the left temperature list is clicked. - Sets the corresponding VSS signal to the selected temperature value. - """ - - self.setTemperature(self.leftTempList, self.HVAC.leftTemp) + def changeTemperature(self, tumbler_widget, change): + """Change tumbler value by incrementing or decrementing.""" + + # use the inc_Value method from the QML object if change is 1 then increment, else decrement + # Access the root object of the QML component + self.LeftTempTumbler.rootObject().property("inc_Value", change) - def rightTempListClicked(self): - """ - Handles the event when an item in the right temperature list is clicked. - Sets the corresponding VSS signal to the selected temperature value. - """ + def onLeftTempChanged(self, newValue): + """Slot to handle changes in left temperature tumbler.""" + + print(f"Left Temperature Tumbler stopped at value: {newValue}°C") + self.setTemperature(newValue, self.HVAC.leftTemp) - self.setTemperature(self.rightTempList, self.HVAC.rightTemp) + def onRightTempChanged(self, newValue): + """Slot to handle changes in right temperature tumbler.""" + + print(f"Right Temperature Tumbler stopped at value: {newValue}°C") + self.setTemperature(newValue, self.HVAC.rightTemp) - def setTemperature(self, list_widget, path): - item = list_widget.currentItem() - if item is not None: - list_widget.scrollToItem(item) - self.kuksa_client.set(path, item.text()[:-2], "targetValue") - print(item.text()) + def setTemperature(self, temp, path): + self.kuksa_client.set(path, str(temp), "targetValue") def leftFanSpeed_sliderChanged(self): """ @@ -140,10 +139,8 @@ class HVACWidget(Base, Form): self.kuksa_client.set(self.HVAC.rightFanSpeed, str(value), "targetValue") print(value) - if __name__ == '__main__': - import sys app = QApplication(sys.argv) w = HVACWidget() w.show() - sys.exit(app.exec()) + sys.exit(app.exec())
\ No newline at end of file diff --git a/Widgets/ICPage.py b/Widgets/ICPage.py index b40177c..0f44703 100644 --- a/Widgets/ICPage.py +++ b/Widgets/ICPage.py @@ -10,7 +10,7 @@ from PyQt6 import uic, QtCore, QtWidgets from PyQt6.QtWidgets import QApplication from PyQt6.QtGui import QIcon, QPixmap, QPainter from PyQt6.QtCore import QObject, pyqtSignal, QThread -from PyQt6.QtWidgets import QWidget, QFrame +from PyQt6.QtWidgets import QWidget, QFrame, QDockWidget from PyQt6.QtQuickWidgets import QQuickWidget import threading @@ -40,10 +40,14 @@ def Gauge(gaugeType): - A QQuickWidget object representing the 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") + 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": @@ -57,11 +61,14 @@ def Gauge(gaugeType): elif gaugeType == "Coolant": gauge.setSource(QtCore.QUrl(Coolant_GaugeQML)) - + gauge.setResizeMode(QQuickWidget.ResizeMode.SizeRootObjectToView) - + gauge.setSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, + QtWidgets.QSizePolicy.Policy.Expanding) + return gauge + class IC_Paths(): def __init__(self): self.speed = "Vehicle.Speed" @@ -73,6 +80,7 @@ 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. @@ -100,7 +108,8 @@ class ICWidget(Base, Form): 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.Coolant_Gauge_Frame = self.findChild( + QFrame, "coolant_gauge_frame") self.Script_toggle = AnimatedToggle() @@ -125,7 +134,8 @@ class ICWidget(Base, Form): self.driveGroupBtns.buttonClicked.connect(self.driveBtnClicked) - Speed_Gauge_Placeholder = self.findChild(QWidget, "Speed_Gauge_Placeholder") + 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) @@ -133,7 +143,8 @@ class ICWidget(Base, Form): self.Speed_slider.setMinimum(0) self.Speed_slider.setMaximum(240) - RPM_Gauge_Placeholder = self.findChild(QWidget, "RPM_Gauge_Placeholder") + 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) @@ -141,26 +152,23 @@ class ICWidget(Base, Form): self.RPM_slider.setMinimum(0) self.RPM_slider.setMaximum(8000) - fuel_Gauge_Placeholder = self.findChild(QWidget, "fuel_Gauge_Placeholder") + 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) + self.Fuel_Gauge_Frame.layout().replaceWidget( + fuel_Gauge_Placeholder, self.Fuel_Gauge) - coolant_Gauge_Placeholder = self.findChild(QWidget, "coolant_Gauge_Placeholder") + 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.Coolant_Gauge_Frame.layout().replaceWidget( + coolant_Gauge_Placeholder, self.Coolant_Gauge) self.coolantTemp_slider.valueChanged.connect( self.update_coolantTemp_monitor) self.fuelLevel_slider.valueChanged.connect( self.update_fuelLevel_monitor) - self.Script_toggle.clicked.connect(self.handle_Script_toggle) self.leftIndicatorBtn.setCheckable(True) self.rightIndicatorBtn.setCheckable(True) self.hazardBtn.setCheckable(True) @@ -169,14 +177,36 @@ class ICWidget(Base, Form): self.rightIndicatorBtn.toggled.connect(self.rightIndicatorBtnClicked) self.hazardBtn.toggled.connect(self.hazardBtnClicked) - self.Playback = CAN_playback() - self.Playback_connections() + self.Script_toggle.clicked.connect(self.handle_Script_toggle) + + try: + self.Playback = CAN_playback() + self.Playback_connections() + except Exception as e: + logging.error(f"Error creating playback object {e}") + + self.TirePressureDock = self.findChild(QDockWidget, "TirePressureDock") + self.TirePressureBtn = self.findChild( + QtWidgets.QPushButton, "TirePressureBtn") + self.TirePressureBtn.clicked.connect(self.toggle_TirePressureDock) + + def toggle_TirePressureDock(self): + if self.TirePressureBtn.isChecked(): + self.Hide_TirePressure(True) + else: + self.Hide_TirePressure(False) + + def Hide_TirePressure(self, bool_arg): + widthExtended = 0 if bool_arg else 400 + self.TirePressureDock.setFixedWidth(widthExtended) + def Playback_connections(self): self.Playback.speedUpdate.connect(self.set_Vehicle_Speed) self.Playback.gearUpdate.connect(self.playback_set_Vehicle_Gear) self.Playback.engineSpeedUpdate.connect(self.set_Vehicle_RPM) - self.Playback.indicatorUpdate.connect(self.playback_set_Vehicle_Indicators) + self.Playback.indicatorUpdate.connect( + self.playback_set_Vehicle_Indicators) def playback_set_Vehicle_Gear(self, gear): if gear == "P": @@ -239,7 +269,8 @@ 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) + gaugeValue = coolantTemp / 100 + self.Coolant_Gauge.rootObject().setProperty('value', gaugeValue) try: self.kuksa_client.set( self.IC.coolantTemp, str(coolantTemp), 'value') @@ -265,7 +296,8 @@ class ICWidget(Base, Form): """ hazardIcon = QPixmap(":/Images/Images/hazard.png") painter = QPainter(hazardIcon) - painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceIn) + painter.setCompositionMode( + QPainter.CompositionMode.CompositionMode_SourceIn) if self.hazardBtn.isChecked(): color = QtCore.Qt.GlobalColor.yellow @@ -294,7 +326,8 @@ class ICWidget(Base, Form): """ leftIndicatorIcon = QPixmap(":/Images/Images/left.png") painter = QPainter(leftIndicatorIcon) - painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceIn) + painter.setCompositionMode( + QPainter.CompositionMode.CompositionMode_SourceIn) if self.leftIndicatorBtn.isChecked(): color = QtCore.Qt.GlobalColor.green @@ -318,7 +351,8 @@ class ICWidget(Base, Form): """ rightIndicatorIcon = QPixmap(":/Images/Images/right.png") painter = QPainter(rightIndicatorIcon) - painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceIn) + painter.setCompositionMode( + QPainter.CompositionMode.CompositionMode_SourceIn) if self.rightIndicatorBtn.isChecked(): color = QtCore.Qt.GlobalColor.green @@ -356,15 +390,28 @@ class ICWidget(Base, Form): def handle_Script_toggle(self): if config.file_playback_enabled(): + if not config.can_interface_enabled(): + self.Script_toggle.showError() + self.Script_toggle.setChecked(False) + return + try: + self.Playback = CAN_playback() + self.Playback_connections() + except Exception as e: + self.Script_toggle.showError() + logging.error(f"Error creating playback object {e}") + return + if self.Script_toggle.isChecked(): # start the playback thread self.thread = QThread() self.Playback.moveToThread(self.thread) self.thread.started.connect(self.Playback.playback_messages) self.thread.start() - # hide sliders + # hide sliders from the layout, their space will be taken by the playback widgets self.Speed_slider.hide() self.RPM_slider.hide() + # set default values for coolent and fuel self.coolantTemp_slider.setValue(90) self.fuelLevel_slider.setValue(50) @@ -448,6 +495,7 @@ 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 index ad0c17e..264bb5d 100644 --- a/Widgets/Keypad.py +++ b/Widgets/Keypad.py @@ -1,7 +1,8 @@ import os import sys from PyQt6 import uic -from PyQt6.QtWidgets import QApplication, QWidget, QPushButton +from PyQt6.QtWidgets import QPushButton +from PyQt6.QtWidgets import QApplication, QWidget import requests from urllib.parse import urljoin diff --git a/Widgets/TirePressure.py b/Widgets/TirePressure.py new file mode 100644 index 0000000..0f3efce --- /dev/null +++ b/Widgets/TirePressure.py @@ -0,0 +1,129 @@ +# Copyright (C) 2024 Suchinton Chakravarty +# Copyright (C) 2024 Konsulko Group +# +# SPDX-License-Identifier: Apache-2.0 + +import os +import sys +from PyQt6 import uic +from PyQt6.QtWidgets import QApplication, QPushButton, QWidget, QLabel +from PyQt6.QtQuickWidgets import QQuickWidget +from PyQt6.QtWidgets import QSizePolicy +from PyQt6.QtCore import QUrl +import logging + +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/TirePressure.ui")) + +# ======================================== + +from extras.KuksaClient import KuksaClient +import res_rc + +class TirePressure_Paths(): + def __init__(self): + self.Tires = { + 0 : "Vehicle.Chassis.Axle.Row1.Wheel.Left.Tire.Pressure", + 1 : "Vehicle.Chassis.Axle.Row1.Wheel.Right.Tire.Pressure", + 2 : "Vehicle.Chassis.Axle.Row2.Wheel.Left.Tire.Pressure", + 3 : "Vehicle.Chassis.Axle.Row2.Wheel.Right.Tire.Pressure" + } + +def TireSelectionWidget(): + """ + A widget for selecting the tire to control. + + Returns: + - A QListWidget. + """ + + QMLPath = os.path.join(current_dir, "../QMLWidgets/Tire_Pressure/TirePressure.qml") + widget = QQuickWidget() + widget.setSource(QUrl.fromLocalFile(QMLPath)) + widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + widget.setResizeMode(QQuickWidget.ResizeMode.SizeRootObjectToView) + return widget + +class TirePressure(Base, Form): + """ + A widget for controlling TirePressure settings. + + Inherits from Base and Form. + """ + + def __init__(self, parent=None): + """ + Initializes the TirePressureWidget. + + Args: + - parent: The parent widget. Defaults to None. + """ + + super(self.__class__, self).__init__(parent) + self.setupUi(self) + + self.TirePressurePath = TirePressure_Paths() + self.kuksa_client = KuksaClient() + self.TireSelector = TireSelectionWidget() + + placeholder = self.findChild(QWidget, "TS_Placeholher") + frame = self.findChild(QWidget, "frame") + frame.layout().replaceWidget(placeholder, self.TireSelector) + self.TPIncreaseBtn = self.findChild(QPushButton, "TPIncreaseBtn") + self.TPDecreaseBtn = self.findChild(QPushButton, "TPDecreaseBtn") + self.TPUnit = self.findChild(QLabel, "TPUnit") + + self.TPIncreaseBtn.clicked.connect(self.increase_pressure) + self.TPDecreaseBtn.clicked.connect(self.decrease_pressure) + + def get_Current(self, tire): + """ + Initializes the TirePressure widget. + """ + + try: + self.TPUnit = self.kuksa_client.get("Vehicle.Cabin.Infotainment.HMI.TirePressureUnit") + return self.kuksa_client.get(self.TirePressurePath.Tires[tire]) + except Exception as e: + logging.error(f"Error getting tire pressure values: {e}") + + + def increase_pressure(self): + """ + Increases the pressure of the selected tire. + """ + + selected_tire = self.TireSelector.rootObject().property("selectedTireIndex") + + current_pressure = self.get_Current(selected_tire) + if current_pressure is None: + return + else: + self.kuksa_client.setValues({self.TirePressurePath.Tires[selected_tire]: current_pressure + 1}) + + + def decrease_pressure(self): + """ + Decreases the pressure of the selected tire. + """ + + selected_tire = self.TireSelector.rootObject().property("selectedTireIndex") + + current_pressure = self.get_Current(selected_tire) + if current_pressure is None: + return + else: + self.kuksa_client.setValues({self.TirePressurePath.Tires[selected_tire]: current_pressure - 1}) + + +if __name__ == '__main__': + app = QApplication(sys.argv) + w = TirePressure() + w.show() + sys.exit(app.exec()) |