Weather: default to 5-day forecast, add weekday+date header line

- forecast_days now defaults to 5 (was 3) across default_settings(),
  check()'s fallback, and the settings form's pre-selected option.
- New show_date setting (on by default): weekday + date in the same
  "Samstag, 25. Juli" format Clock already used. Combined with the
  city name into one header line above the icon/temp block when both
  are on ("Münster · Samstag, 25. Juli"), each independently
  toggleable.
- Moved the weekday/month name lists and the "Weekday, D. Month"
  formatting out of clock.py into render_utils.format_date_de(), so
  Weather reuses the exact same formatting instead of a second copy
  that could drift.
This commit is contained in:
Honey committed 2026-07-25 10:38:14 +02:00
1 parent 78337a99d2
commit 7601f746fe
5 files changed
+50 -32

No files matched your search

+27 -20
View File
@@ -8,7 +8,7 @@ import requests
from PIL import Image, ImageDraw
from screens.base import Screen
from screens.render_utils import load_font, text_width, truncate_to_width
from screens.render_utils import format_date_de, load_font, text_width, truncate_to_width
from screens.weather_icons import WMO_CODES, draw_weather_icon
BLACK = (0, 0, 0)
@@ -31,12 +31,13 @@ class WeatherScreen(Screen):
def default_settings(self) -> dict:
return {
"city": "", "latitude": None, "longitude": None, "forecast_days": 3, "update_minutes": 30,
"city": "", "latitude": None, "longitude": None, "forecast_days": 5, "update_minutes": 30,
"show_feels_like": True,
"show_high_low": True,
"show_rain_chance": True,
"show_hourly_graph": True,
"show_city": True,
"show_date": True,
}
def get_poll_interval(self, settings: dict) -> int:
@@ -79,9 +80,9 @@ class WeatherScreen(Screen):
logger.warning("Weather screen has no latitude/longitude configured")
return None
forecast_days = settings.get("forecast_days", 3)
forecast_days = settings.get("forecast_days", 5)
if forecast_days not in FORECAST_DAY_CHOICES:
forecast_days = 3
forecast_days = 5
response = requests.get(
"https://api.open-meteo.com/v1/forecast",
@@ -214,26 +215,32 @@ class WeatherScreen(Screen):
text_block_h = temp_h + text_gap + desc_h + ((text_gap + extra_h) if extra_line else 0)
current_h = max(icon_size, text_block_h)
# City name, above the icon/temp block -- just the city itself, not
# the full "City, State, Country" geocode label (too long/cluttered
# for a dashboard header). Nothing to show for manually-entered
# coordinates, since there's no resolved place name for those.
city_font = load_font(size=int(scale * 0.045), bold=True)
city_label = ""
city_h = city_gap = city_top = 0
# Header line above the icon/temp block: city name (just the city
# itself, not the full "City, State, Country" geocode label -- too
# cluttered for a dashboard) and/or today's weekday + date, same
# format as the Clock screen. Nothing to show for city specifically
# with manually-entered coordinates, since there's no resolved place
# name for those.
header_font = load_font(size=int(scale * 0.045), bold=True)
header_parts = []
if settings.get("show_city", True) and settings.get("city"):
city_label = truncate_to_width(draw, settings["city"].split(",")[0].strip(), city_font, width - 2 * pad)
if city_label:
city_left, city_top, city_right, city_bottom = draw.textbbox((0, 0), city_label, font=city_font)
city_h = city_bottom - city_top
city_gap = height * 0.025
header_parts.append(settings["city"].split(",")[0].strip())
if settings.get("show_date", True):
header_parts.append(format_date_de())
header_label = truncate_to_width(draw, " · ".join(header_parts), header_font, width - 2 * pad) if header_parts else ""
total_top_h = city_h + city_gap + current_h
header_h = header_gap = header_top = 0
if header_label:
header_left, header_top, header_right, header_bottom = draw.textbbox((0, 0), header_label, font=header_font)
header_h = header_bottom - header_top
header_gap = height * 0.025
total_top_h = header_h + header_gap + current_h
top_pad = (height - total_top_h) / 2 if lower_sections == 0 else height * 0.05
if city_label:
draw.text((pad, top_pad - city_top), city_label, font=city_font, fill="black")
block_top = top_pad + city_h + city_gap
if header_label:
draw.text((pad, top_pad - header_top), header_label, font=header_font, fill="black")
block_top = top_pad + header_h + header_gap
icon_cx = pad + icon_size / 2
icon_cy = block_top + current_h / 2