Skip to content

Commit 453f4e0

Browse files
author
queenkjuul
committed
[WIP] Add basic weather information to screensaver
1 parent f4fb467 commit 453f4e0

File tree

4 files changed

+154
-0
lines changed

4 files changed

+154
-0
lines changed

src/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ app_py = [
3232
'status.py',
3333
'unlock.py',
3434
'volumeControl.py',
35+
'weather.py'
3536
]
3637

3738
app_css = [

src/stage.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from util import utils, trackers, settings
2121
from util.eventHandler import EventHandler
2222
from util.utils import DEBUG
23+
from weather import WeatherWidget
2324

2425
class Stage(Gtk.Window):
2526
"""
@@ -69,6 +70,7 @@ def __init__(self, manager, away_message):
6970
self.overlay = None
7071
self.clock_widget = None
7172
self.albumart_widget = None
73+
self.weather_widget = None
7274
self.unlock_dialog = None
7375
self.audio_panel = None
7476
self.info_panel = None
@@ -291,6 +293,11 @@ def setup_delayed_components(self, data=None):
291293
except Exception as e:
292294
print("Problem setting up albumart widget: %s" % str(e))
293295
self.albumart_widget = None
296+
try:
297+
self.setup_weather()
298+
except Exception as e:
299+
print("Problem setting up weather widget: %s" % str(e))
300+
self.weather_widget = None
294301
try:
295302
self.setup_status_bars()
296303
except Exception as e:
@@ -324,6 +331,13 @@ def destroy_children(self):
324331
except Exception as e:
325332
print(e)
326333

334+
try:
335+
if self.weather_widget is not None:
336+
self.weather_widget.stop_positioning()
337+
self.weather_widget.destroy()
338+
except Exception as e:
339+
print(e)
340+
327341
try:
328342
if self.info_panel is not None:
329343
self.info_panel.destroy()
@@ -345,6 +359,7 @@ def destroy_children(self):
345359
self.unlock_dialog = None
346360
self.clock_widget = None
347361
self.albumart_widget = None
362+
self.weather_widget = None
348363
self.info_panel = None
349364
self.audio_panel = None
350365
self.osk = None
@@ -504,6 +519,23 @@ def setup_albumart(self):
504519
if settings.get_show_albumart():
505520
self.albumart_widget.start_positioning()
506521

522+
def setup_weather(self):
523+
"""
524+
Construct the Weather widget and add it to the overlay, but only actually
525+
show it if we're a) Not running a plug-in, and b) The user wants it via
526+
preferences.
527+
528+
Initially invisible, regardless - its visibility is controlled via its
529+
own positioning timer.
530+
"""
531+
self.weather_widget = WeatherWidget(None, status.screen.get_mouse_monitor())
532+
self.add_child_widget(self.weather_widget)
533+
534+
self.floaters.append(self.weather_widget)
535+
536+
if settings.get_show_albumart():
537+
self.weather_widget.start_positioning()
538+
507539
def setup_osk(self):
508540
self.osk = OnScreenKeyboard()
509541

src/util/settings.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030

3131
SHOW_CLOCK_KEY = "show-clock"
3232
SHOW_ALBUMART = "show-album-art"
33+
SHOW_WEATHER = "show-weather"
34+
WEATHER_API_KEY = "weather-api-key"
35+
WEATHER_LOCATION = "weather-location"
36+
WEATHER_UNITS = "weather-units"
3337
ALLOW_SHORTCUTS = "allow-keyboard-shortcuts"
3438
ALLOW_MEDIA_CONTROL = "allow-media-control"
3539
SHOW_INFO_PANEL = "show-info-panel"
@@ -133,6 +137,28 @@ def get_show_clock():
133137
def get_show_albumart():
134138
return ss_settings.get_boolean(SHOW_ALBUMART)
135139

140+
def get_show_weather():
141+
# return ss_settings.get_boolean(SHOW_WEATHER)
142+
return True
143+
144+
def get_weather_api_key():
145+
# return ss_settings.get_string(WEATHER_API_KEY)
146+
return ""
147+
148+
def get_weather_location():
149+
# return ss_settings.get_string(WEAThER_LOCATION) # string LAT,LON (eventually)
150+
return "chicago,il,us"
151+
152+
def get_weather_units():
153+
# return ss_settings.get_string(WEATHER_UNITS) # metric || imperial
154+
return "imperial"
155+
156+
def get_weather_font():
157+
# reusing the Clock widget Time font for now (it's big)
158+
time_font = ss_settings.get_string(FONT_TIME_KEY)
159+
160+
return _check_string(time_font)
161+
136162
def get_allow_shortcuts():
137163
return ss_settings.get_boolean(ALLOW_SHORTCUTS)
138164

src/weather.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/python3
2+
import json
3+
4+
from gi.repository import CinnamonDesktop, GLib, Gtk, Gio, Pango
5+
6+
from util import utils, trackers, settings
7+
from baseWindow import BaseWindow
8+
from floating import Floating
9+
import requests
10+
11+
MAX_WIDTH = 320
12+
MAX_WIDTH_LOW_RES = 200
13+
14+
WEATHER_URL = "https://api.openweathermap.org/data/2.5/weather"
15+
16+
class WeatherWidget(Floating, BaseWindow):
17+
"""
18+
WeatherWidget displays current weather on screen
19+
20+
It is a child of the Stage's GtkOverlay, and its placement is
21+
controlled by the overlay's child positioning function.
22+
23+
When not Awake, it positions itself around all monitors
24+
using a timer which randomizes its halign and valign properties
25+
as well as its current monitor.
26+
"""
27+
def __init__(self, away_message=None, initial_monitor=0, low_res=False):
28+
super(WeatherWidget, self).__init__(initial_monitor)
29+
self.get_style_context().add_class("weather")
30+
self.set_halign(Gtk.Align.START)
31+
32+
self.set_property("margin", 6)
33+
34+
self.low_res = low_res
35+
36+
if not settings.get_show_weather():
37+
return
38+
39+
self.away_message = away_message
40+
41+
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
42+
self.add(box)
43+
box.show()
44+
45+
self.label = Gtk.Label()
46+
self.label.show()
47+
self.label.set_line_wrap(True)
48+
self.label.set_alignment(0.5, 0.5)
49+
50+
box.pack_start(self.label, True, False, 6)
51+
52+
self.msg_label = Gtk.Label()
53+
self.msg_label.show()
54+
self.msg_label.set_line_wrap(True)
55+
self.msg_label.set_alignment(0.5, 0.5)
56+
57+
if self.low_res:
58+
self.msg_label.set_max_width_chars(50)
59+
else:
60+
self.msg_label.set_max_width_chars(80)
61+
62+
box.pack_start(self.msg_label, True, True, 6)
63+
64+
self.update_weather()
65+
66+
def update_weather(self):
67+
default_message = GLib.markup_escape_text (settings.get_default_away_message(), -1)
68+
font_message = Pango.FontDescription.from_string(settings.get_message_font())
69+
font_weather = Pango.FontDescription.from_string(settings.get_weather_font())
70+
71+
response = requests.get(WEATHER_URL,
72+
{ "q": settings.get_weather_location(),
73+
"units": settings.get_weather_units(),
74+
"appid": settings.get_weather_api_key()})
75+
data = response.json()
76+
default_message = data["weather"][0]["main"] + " in " + data["name"]
77+
78+
if self.low_res:
79+
msg_size = font_message.get_size() * .66
80+
font_message.set_size(int(msg_size))
81+
82+
markup = '<b><span font_desc=\"%s\" foreground=\"#CCCCCC\">%s</span></b>\n ' %\
83+
(font_message.to_string(), default_message)
84+
85+
self.label.set_markup('<span font_desc=\"%s\">%s°</span>' % (font_weather.to_string(), data['main']['temp']))
86+
self.msg_label.set_markup(markup)
87+
88+
def set_message(self, msg=""):
89+
self.away_message = msg
90+
self.update_weather()
91+
92+
@staticmethod
93+
def on_destroy(data=None):
94+
# placeholder
95+
print("shut down weather widget: " + data)

0 commit comments

Comments
 (0)