from PySide6.QtGui import QPixmap from PySide6.QtWidgets import QGroupBox, QHBoxLayout, QLabel, QVBoxLayout, QGridLayout from dcs.weather import CloudPreset, Weather as PydcsWeather from game.timeofday import TimeOfDay from game.utils import mps from game.weather.conditions import Conditions from qt_ui import uiconstants as CONST class QWeatherWidget(QGroupBox): """ UI Component to display current weather forecast """ turn = None conditions = None def __init__(self): super(QWeatherWidget, self).__init__("") self.setProperty("style", "QWeatherWidget") self.icons = { TimeOfDay.Dawn: CONST.ICONS["Dawn"], TimeOfDay.Day: CONST.ICONS["Day"], TimeOfDay.Dusk: CONST.ICONS["Dusk"], TimeOfDay.Night: CONST.ICONS["Night"], } self.layout = QHBoxLayout() self.setLayout(self.layout) self.makeWeatherIcon() self.makeCloudRainFogWidget() self.makeWindsWidget() def makeWeatherIcon(self): """Makes the Weather Icon Widget""" self.weather_icon = QLabel() self.weather_icon.setPixmap(self.icons[TimeOfDay.Dawn]) self.layout.addWidget(self.weather_icon) def makeCloudRainFogWidget(self): """Makes the Cloud, Rain, Fog Widget""" self.textLayout = QVBoxLayout() self.layout.addLayout(self.textLayout) self.forecastClouds = self.makeLabel() self.textLayout.addWidget(self.forecastClouds) self.forecastRain = self.makeLabel() self.textLayout.addWidget(self.forecastRain) self.forecastFog = self.makeLabel() self.textLayout.addWidget(self.forecastFog) def makeWindsWidget(self): """Factory for the winds widget.""" windsLayout = QGridLayout() self.layout.addLayout(windsLayout) windsLayout.addWidget(self.makeIcon(CONST.ICONS["Weather_winds"]), 0, 0, 3, 1) windsLayout.addWidget(self.makeLabel("At GL"), 0, 1) windsLayout.addWidget(self.makeLabel("At FL08"), 1, 1) windsLayout.addWidget(self.makeLabel("At FL26"), 2, 1) self.windGLSpeedLabel = self.makeLabel("0kts") self.windGLDirLabel = self.makeLabel("0º") windsLayout.addWidget(self.windGLSpeedLabel, 0, 2) windsLayout.addWidget(self.windGLDirLabel, 0, 3) self.windFL08SpeedLabel = self.makeLabel("0kts") self.windFL08DirLabel = self.makeLabel("0º") windsLayout.addWidget(self.windFL08SpeedLabel, 1, 2) windsLayout.addWidget(self.windFL08DirLabel, 1, 3) self.windFL26SpeedLabel = self.makeLabel("0kts") self.windFL26DirLabel = self.makeLabel("0º") windsLayout.addWidget(self.windFL26SpeedLabel, 2, 2) windsLayout.addWidget(self.windFL26DirLabel, 2, 3) def makeLabel(self, text: str = "") -> QLabel: """Shorthand to generate a QLabel with widget standard style :arg pixmap QPixmap for the icon. """ label = QLabel(text) label.setProperty("style", "text-sm") return label def makeIcon(self, pixmap: QPixmap) -> QLabel: """Shorthand to generate a QIcon with pixmap. :arg pixmap QPixmap for the icon. """ icon = QLabel() icon.setPixmap(pixmap) return icon def setCurrentTurn(self, turn: int, conditions: Conditions) -> None: """Sets the turn information display. :arg turn Current turn number. :arg conditions Current time and weather conditions. """ self.turn = turn self.conditions = conditions self.update_forecast() self.updateWinds() def updateWinds(self): """Updates the UI with the current conditions wind info.""" windGlSpeed = mps(self.conditions.weather.wind.at_0m.speed or 0) windGlDir = str(self.conditions.weather.wind.at_0m.direction or 0).rjust(3, "0") self.windGLSpeedLabel.setText(f"{int(windGlSpeed.knots)}kts") self.windGLDirLabel.setText(f"{windGlDir}º") windFL08Speed = mps(self.conditions.weather.wind.at_2000m.speed or 0) windFL08Dir = str(self.conditions.weather.wind.at_2000m.direction or 0).rjust( 3, "0" ) self.windFL08SpeedLabel.setText(f"{int(windFL08Speed.knots)}kts") self.windFL08DirLabel.setText(f"{windFL08Dir}º") windFL26Speed = mps(self.conditions.weather.wind.at_8000m.speed or 0) windFL26Dir = str(self.conditions.weather.wind.at_8000m.direction or 0).rjust( 3, "0" ) self.windFL26SpeedLabel.setText(f"{int(windFL26Speed.knots)}kts") self.windFL26DirLabel.setText(f"{windFL26Dir}º") def update_forecast_from_preset(self, preset: CloudPreset) -> None: self.forecastFog.setText("No fog") if "Rain" in preset.name: self.forecastRain.setText("Rain") self.update_forecast_icons("rain") else: self.forecastRain.setText("No rain") self.update_forecast_icons("partly-cloudy") # We get a description like the following for the cloud preset. # # 09 ##Two Layer Broken/Scattered \nMETAR:BKN 7.5/10 SCT 20/22 FEW41 # # The second line is probably interesting but doesn't fit into the widget # currently, so for now just extract the first line. self.forecastClouds.setText(preset.description.splitlines()[0].split("##")[1]) def update_forecast(self): """Updates the Forecast Text and icon with the current conditions wind info.""" if ( self.conditions.weather.clouds and self.conditions.weather.clouds.preset is not None ): self.update_forecast_from_preset(self.conditions.weather.clouds.preset) return if self.conditions.weather.clouds is None: cloud_density = 0 precipitation = None else: cloud_density = self.conditions.weather.clouds.density precipitation = self.conditions.weather.clouds.precipitation if not cloud_density: self.forecastClouds.setText("Clear") weather_type = "clear" elif cloud_density < 3: self.forecastClouds.setText("Partly Cloudy") weather_type = "partly-cloudy" elif cloud_density < 5: self.forecastClouds.setText("Mostly Cloudy") weather_type = "partly-cloudy" else: self.forecastClouds.setText("Totally Cloudy") weather_type = "partly-cloudy" if precipitation == PydcsWeather.Preceptions.Rain: self.forecastRain.setText("Rain") weather_type = "rain" elif precipitation == PydcsWeather.Preceptions.Thunderstorm: self.forecastRain.setText("Thunderstorm") weather_type = "thunderstorm" else: self.forecastRain.setText("No rain") if not self.conditions.weather.fog is not None: self.forecastFog.setText("No fog") else: visibility = round(self.conditions.weather.fog.visibility.nautical_miles, 1) self.forecastFog.setText(f"Fog vis: {visibility}nm") if cloud_density > 1: weather_type = "cloudy-fog" else: weather_type = "fog" self.update_forecast_icons(weather_type) def update_forecast_icons(self, weather_type: str) -> None: time = "night" if self.conditions.time_of_day == TimeOfDay.Night else "day" icon_key = f"Weather_{time}-{weather_type}" icon = CONST.ICONS.get(icon_key) or CONST.ICONS["Weather_night-partly-cloudy"] self.weather_icon.setPixmap(icon)