diff --git a/README.md b/README.md
index 3493b39..d7a5ccb 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,22 @@
diff --git a/data/icons/hicolor/scalable/weather_icons/wind.svg b/data/icons/hicolor/scalable/weather_icons/wind.svg
new file mode 100644
index 0000000..56d7854
--- /dev/null
+++ b/data/icons/hicolor/scalable/weather_icons/wind.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/data/icons/meson.build b/data/icons/meson.build
index 6e6304f..cb2228e 100644
--- a/data/icons/meson.build
+++ b/data/icons/meson.build
@@ -32,6 +32,7 @@ install_data(
join_paths(scalable_dir, 'partly-cloudy-day-fog.svg'),
join_paths(scalable_dir, 'partly-cloudy-night-fog.svg'),
join_paths(scalable_dir, 'rain.svg'),
+ join_paths(scalable_dir, 'wind.svg'),
join_paths(scalable_dir, 'raindrop.svg'),
join_paths(scalable_dir, 'raindrops.svg'),
join_paths(scalable_dir, 'overcast-rain.svg'),
diff --git a/src/Models.py b/src/Models.py
index 4709fb4..69438ff 100644
--- a/src/Models.py
+++ b/src/Models.py
@@ -1,6 +1,4 @@
# Models for All weather data data
-import time
-
class CurrentWeather:
total_instances = 0
diff --git a/src/__init__.py b/src/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/src/backendAirPollution.py b/src/backendAirPollution.py
index 264d6f6..03c08d5 100644
--- a/src/backendAirPollution.py
+++ b/src/backendAirPollution.py
@@ -21,7 +21,7 @@ def current_air_pollution(latitude: float, longitude: float, **kwargs):
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
- def _get_current_air_pollution(self,lat,lon):
+ def _get_current_air_pollution(self, lat, lon):
current_args = [
"european_aqi",
"us_aqi",
diff --git a/src/backendWeather.py b/src/backendWeather.py
index 7759ecb..5939247 100644
--- a/src/backendWeather.py
+++ b/src/backendWeather.py
@@ -1,40 +1,40 @@
-from typing import List
import requests
import datetime
from gi.repository import Gio
-
base_url = "https://api.open-meteo.com/v1/forecast"
-class Weather():
+
+class Weather:
"""
See Documentation at: https://open-meteo.com/en/docs
"""
+
def __init__(self) -> None:
- global settings,measurement_type,temperature_unit,wind_speed_unit
+ global settings, measurement_type, temperature_unit, wind_speed_unit
settings = Gio.Settings(schema_id="io.github.amit9838.weather")
- measurement_type = settings.get_string('measure-type')
+ measurement_type = settings.get_string("measure-type")
if measurement_type == "imperial":
temperature_unit = "fahrenheit"
wind_speed_unit = "mph"
+
# Current Weather =============================================
@staticmethod
def current_weather(latitude: float, longitude: float, **kwargs):
-
url = base_url + f"?latitude={latitude}&longitude={longitude}"
# Check for kwargs keyword parameters
- if 'current' in kwargs:
- current_fields = ",".join(kwargs.get('current'))
- url = url+f"¤t={current_fields}"
-
+ if "current" in kwargs:
+ current_fields = ",".join(kwargs.get("current"))
+ url = url + f"¤t={current_fields}"
+
if measurement_type == "imperial":
url += f"&temperature_unit={temperature_unit}&wind_speed_unit={wind_speed_unit}"
try:
- url = url+f"&timeformat=unixtime"
+ url = url + f"&timeformat=unixtime"
response = requests.get(url)
response.raise_for_status() # Raise an exception if the request was unsuccessful
data = response.json()
@@ -42,7 +42,7 @@ def current_weather(latitude: float, longitude: float, **kwargs):
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
- def _get_current_weather(self,lat,lon):
+ def _get_current_weather(self, lat, lon):
current_args = [
"temperature_2m",
"relativehumidity_2m",
@@ -53,27 +53,25 @@ def _get_current_weather(self,lat,lon):
"weathercode",
"surface_pressure",
"windspeed_10m",
- "winddirection_10m"
+ "winddirection_10m",
]
- return self.current_weather(lat,lon,current = current_args)
-
+ return self.current_weather(lat, lon, current=current_args)
# Hourly Forecast ==============================================
@staticmethod
def forecast_hourly(latitude: float, longitude: float, **kwargs):
-
url = base_url + f"?latitude={latitude}&longitude={longitude}"
# Check for kwargs keyword parameters
- if 'hourly' in kwargs:
- hourly_fields = ",".join(kwargs.get('hourly'))
- url = url+f"&hourly={hourly_fields}"
-
+ if "hourly" in kwargs:
+ hourly_fields = ",".join(kwargs.get("hourly"))
+ url = url + f"&hourly={hourly_fields}"
+
if measurement_type == "imperial":
url += f"&temperature_unit={temperature_unit}&wind_speed_unit={wind_speed_unit}"
try:
- url = url+f"&timeformat=unixtime"
+ url = url + f"&timeformat=unixtime"
response = requests.get(url)
response.raise_for_status() # Raise an exception if the request was unsuccessful
data = response.json()
@@ -81,49 +79,50 @@ def forecast_hourly(latitude: float, longitude: float, **kwargs):
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
-
- def _get_hourly_forecast(self,lat,lon):
+ def _get_hourly_forecast(self, lat, lon):
hourly_args = [
- 'temperature_2m',
- 'relativehumidity_2m',
- 'dewpoint_2m',
- 'apparent_temperature',
- 'weathercode',
- 'precipitation',
- 'surface_pressure',
- 'visibility',
- 'windspeed_10m',
- 'wind_direction_10m',
- 'uv_index',
- 'is_day'
+ "temperature_2m",
+ "relativehumidity_2m",
+ "dewpoint_2m",
+ "apparent_temperature",
+ "weathercode",
+ "precipitation",
+ "precipitation_probability",
+ "surface_pressure",
+ "visibility",
+ "windspeed_10m",
+ "wind_direction_10m",
+ "uv_index",
+ "is_day",
]
today = datetime.datetime.today().date()
- tomorrow = today+datetime.timedelta(days=1)
- return self.forecast_hourly(lat, lon,hourly=hourly_args,start_date=today,end_date=tomorrow)
-
+ tomorrow = today + datetime.timedelta(days=1)
+ return self.forecast_hourly(
+ lat, lon, hourly=hourly_args, start_date=today, end_date=tomorrow
+ )
# Forecast daily ====================================================
@staticmethod
def forecast_daily(latitude: float, longitude: float, **kwargs):
url = base_url + f"?latitude={latitude}&longitude={longitude}"
- if 'daily' in kwargs:
- hourly_fields = ",".join(kwargs.get('daily'))
- url = url+f"&daily={hourly_fields}"
+ if "daily" in kwargs:
+ hourly_fields = ",".join(kwargs.get("daily"))
+ url = url + f"&daily={hourly_fields}"
- if 'timezone' in kwargs:
- url = url+f"&timezone={kwargs.get('timezone')}"
- if 'start_date' in kwargs:
- url = url+f"&start_date={kwargs.get('start_date')}"
+ if "timezone" in kwargs:
+ url = url + f"&timezone={kwargs.get('timezone')}"
+ if "start_date" in kwargs:
+ url = url + f"&start_date={kwargs.get('start_date')}"
- if 'end_date' in kwargs:
- url = url+f"&end_date={kwargs.get('end_date')}"
+ if "end_date" in kwargs:
+ url = url + f"&end_date={kwargs.get('end_date')}"
if measurement_type == "imperial":
url += f"&temperature_unit={temperature_unit}&wind_speed_unit={wind_speed_unit}"
try:
- url = url+f"&timeformat=unixtime"
+ url = url + f"&timeformat=unixtime"
response = requests.get(url)
response.raise_for_status() # Raise an exception if the request was unsuccessful
data = response.json()
@@ -131,7 +130,7 @@ def forecast_daily(latitude: float, longitude: float, **kwargs):
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
- def _get_daily_forecast(self,lat,lon):
+ def _get_daily_forecast(self, lat, lon):
daily_args = [
"weathercode",
"temperature_2m_max",
@@ -143,4 +142,4 @@ def _get_daily_forecast(self,lat,lon):
"windspeed_10m_max",
]
- return self.forecast_daily(lat,lon,daily=daily_args,timezone="GMT")
+ return self.forecast_daily(lat, lon, daily=daily_args, timezone="GMT")
diff --git a/src/constants.py b/src/constants.py
index 5a013df..38ae811 100644
--- a/src/constants.py
+++ b/src/constants.py
@@ -63,7 +63,11 @@
"95n": icon_loc + "thunderstorms-rain.svg",
"96n": icon_loc + "thunderstorms-night-overcast-snow.svg",
"99n": icon_loc + "snowflake.svg",
+
"arrow": icon_loc + "arrow.svg",
+ "raindrop": icon_loc + "raindrop.svg",
+ "raindrops": icon_loc + "raindrops.svg",
+ "wind": icon_loc + "wind.svg",
}
bg_css = {
diff --git a/src/css.py b/src/css.py
index 7145f84..c7a5a24 100644
--- a/src/css.py
+++ b/src/css.py
@@ -137,7 +137,7 @@
}
.custom_card_forecast_item{
- padding: .15rem 1.5rem;
+ padding: 0.15rem 1.5rem;
border-radius: .7rem;
}
diff --git a/src/frontendForecast.py b/src/frontendForecast.py
index ad70823..c32cfe9 100644
--- a/src/frontendForecast.py
+++ b/src/frontendForecast.py
@@ -89,6 +89,7 @@ def page_stacks(self, page_name):
orientation=Gtk.Orientation.VERTICAL, margin_top=0, margin_bottom=0)
scrolled_window.set_child(forecast_container)
+
# Get Tomorrow's data from hourly forecast
tomorrow_date_time_list = [d_t for d_t in hourly_data.time.get("data") if int(
datetime.fromtimestamp(d_t).strftime(r"%d")) == (datetime.today() + timedelta(days=1)).date().day]
@@ -135,12 +136,41 @@ def page_stacks(self, page_name):
icon_main.set_halign(Gtk.Align.END)
icon_main.set_hexpand(True)
icon_main.set_pixel_size(50)
- icon_main.set_margin_end(60)
+ icon_main.set_margin_end(30)
forecast_item_grid.attach(icon_main, 1, 0, 1, 1)
+ forecast_cond_grid = Gtk.Grid(valign=Gtk.Align.CENTER,margin_end = 20)
+ forecast_item_grid.attach(forecast_cond_grid, 2, 0, 1, 1)
+
+ # prec probability
+ if page_name == 'tomorrow':
+ prec_probability = hourly_data.precipitation_probability.get("data")[i]
+ wind_probability = hourly_data.windspeed_10m.get("data")[i]
+
+
+ drop_icon = Gtk.Image().new_from_file(icons["raindrop"])
+ drop_icon.set_pixel_size(25)
+ drop_icon.set_halign(Gtk.Align.START)
+ forecast_cond_grid.attach(drop_icon, 0, 0, 1, 1)
+
+ prec_probability_label = Gtk.Label(label=f" {prec_probability}%", margin_top=5)
+ prec_probability_label.set_halign(Gtk.Align.START)
+ forecast_cond_grid.attach(prec_probability_label, 1, 0, 1, 1)
+
+ # Wind speed probability
+ wind_icon = Gtk.Image().new_from_file(icons["wind"])
+ wind_icon.set_pixel_size(25)
+ wind_icon.set_halign(Gtk.Align.START)
+ forecast_cond_grid.attach(wind_icon, 0, 1, 1, 1)
+ speed_unit= hourly_data.windspeed_10m.get("unit")
+ wind_probability_label = Gtk.Label(label=f" {wind_probability} {speed_unit}", margin_top=5)
+ forecast_cond_grid.attach(wind_probability_label, 1, 1, 1, 1)
+
+
# Temp label grid
temp_label_grid = Gtk.Grid(valign=Gtk.Align.CENTER)
- forecast_item_grid.attach(temp_label_grid, 2, 0, 1, 1)
+ forecast_item_grid.attach(temp_label_grid, 3, 0, 1, 1)
+
# Max temp label ======
temp_max_text = hourly_data.temperature_2m.get("data")[i]
@@ -149,7 +179,7 @@ def page_stacks(self, page_name):
temp_max = Gtk.Label(label=f"{temp_max_text:.0f}° ", margin_start=10,)
temp_max.set_css_classes(['text-3', 'bold-2'])
- temp_label_grid.attach(temp_max, 0, 0, 1, 1)
+ temp_label_grid.attach(temp_max, 1, 0, 1, 1)
# Min temp label ======
temp_min_text = hourly_data.temperature_2m.get("data")[i]
@@ -158,4 +188,4 @@ def page_stacks(self, page_name):
temp_min = Gtk.Label(label=f" {temp_min_text:.0f}°", margin_top=5)
temp_min.set_css_classes(['light-4'])
- temp_label_grid.attach(temp_min, 0, 1, 1, 1)
+ temp_label_grid.attach(temp_min, 1, 1, 1, 1)
diff --git a/src/frontendHourlyDetails.py b/src/frontendHourlyDetails.py
index 0633ac5..3643fb8 100644
--- a/src/frontendHourlyDetails.py
+++ b/src/frontendHourlyDetails.py
@@ -151,8 +151,6 @@ def create_stack_page(self, page_name):
"Enjoy a rain-free day today!",
"Umbrella status: resting. No precipitation in sight !",
"No rain in sight today!"
-
-
]
no_prec_label = Gtk.Label(label=no_prec_labels[random.randint(0,len(no_prec_labels)-1)])
no_prec_label.set_css_classes(["text-3a", "bold-3", "light-2"])
diff --git a/src/main.py b/src/main.py
index e8e2007..523fade 100644
--- a/src/main.py
+++ b/src/main.py
@@ -1,6 +1,6 @@
# main.py
#
-# Copyright 2023 Amit
+# Copyright 2024 Amit
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/src/meson.build b/src/meson.build
index 8c919c1..0ddd3e7 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -28,7 +28,6 @@ configure_file(
weather_sources = [
- '__init__.py',
'main.py',
'weather.py',
'weatherData.py',
diff --git a/src/units.py b/src/units.py
index 58aa201..eb4b46e 100644
--- a/src/units.py
+++ b/src/units.py
@@ -3,15 +3,3 @@
def get_measurement_type():
settings = Gio.Settings.new("io.github.amit9838.weather")
return settings.get_string("measure-type")
-
-# Units and measurements
-measurements = {
- "metric":{"temp_unit":"°C",
- "speed_unit":'km/h',"speed_mul":3.6, # convert speed from m/s to km/h
- "dist_unit":'km',"dist_mul":0.001
- },
- "imperial":{"temp_unit":"°F",
- "speed_unit":'mph',"speed_mul":1, #speed miles/hr
- "dist_unit":'miles',"dist_mul":0.0006213712,
- }
- }
diff --git a/src/utils.py b/src/utils.py
index a750d1f..b96df63 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -2,20 +2,12 @@
import socket
import json
from datetime import datetime, timedelta, timezone
-from gi.repository import Adw,Gio
+from gi.repository import Adw, Gio
current_weather_data = None
air_pollution_data = None
forecast_weather_data = None
-def get_weather_data():
- return current_weather_data,air_pollution_data,forecast_weather_data
-
-def set_weather_data(current,air_pollution,forecast):
- global current_weather_data, air_pollution_data,forecast_weather_data
- current_weather_data = current
- air_pollution_data = air_pollution
- forecast_weather_data = forecast
def check_internet_connection():
has_active_internet = False
@@ -26,21 +18,26 @@ def check_internet_connection():
except OSError:
return has_active_internet
+
def get_selected_city_coords():
settings = Gio.Settings.new("io.github.amit9838.weather")
- selected_city = int(str(settings.get_value('selected-city')))
- added_cities = list(settings.get_value('added-cities'))
- city_loc = added_cities[selected_city].split(',')
- return city_loc[-2],city_loc[-1] #latitude,longitude
+ selected_city = int(str(settings.get_value("selected-city")))
+ added_cities = list(settings.get_value("added-cities"))
+ city_loc = added_cities[selected_city].split(",")
+ return city_loc[-2], city_loc[-1] # latitude,longitude
+
-def create_toast(text,priority=0):
+def create_toast(text, priority=0):
toast = Adw.Toast.new(text)
toast.set_priority(Adw.ToastPriority(priority))
return toast
+
def convert_to_local_time(timestamp, timezone_stamp):
- hour_offset_from_utc = (timezone_stamp)/3600
- return datetime.fromtimestamp(timestamp,tz=timezone.utc) + timedelta(hours=hour_offset_from_utc)
+ hour_offset_from_utc = (timezone_stamp) / 3600
+ return datetime.fromtimestamp(timestamp, tz=timezone.utc) + timedelta(
+ hours=hour_offset_from_utc
+ )
def get_cords():
@@ -60,28 +57,28 @@ def get_my_tz_offset_from_utc():
return f"Error: {str(e)}"
-def get_tz_offset_by_cord(lat,lon):
+def get_tz_offset_by_cord(lat, lon):
url = f"https://api.geotimezone.com/public/timezone?latitude={lat}&longitude={lon}"
res = requests.get(url)
if res.status_code != 200:
return 0
-
+
res = json.loads(res.text)
if res.get("offset") is None:
return 0
-
+
offset_arr = res.get("offset")[3:].split(":")
offset_arr = [int(x) for x in offset_arr]
- epoch_hr = abs(offset_arr[0])*3600
+ epoch_hr = abs(offset_arr[0]) * 3600
epoch_s = 0
-
+
if len(offset_arr) > 1:
- epoch_s = offset_arr[1]*60
-
- epoch_offset = epoch_hr+epoch_s
+ epoch_s = offset_arr[1] * 60
+
+ epoch_offset = epoch_hr + epoch_s
if offset_arr[0] < 0:
epoch_offset *= -1
-
+
return epoch_offset
diff --git a/src/weather.in b/src/weather.in
index ad5d32c..f839422 100755
--- a/src/weather.in
+++ b/src/weather.in
@@ -2,7 +2,7 @@
# weather.in
#
-# Copyright 2023 Amit
+# Copyright 2024 Amit
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/src/weather.py b/src/weather.py
index ba0a04e..765428c 100644
--- a/src/weather.py
+++ b/src/weather.py
@@ -4,7 +4,7 @@
gi.require_version("Gtk", "4.0")
gi.require_version("Adw", "1")
-from gi.repository import Gtk, Adw, Gio, GLib
+from gi.repository import Gtk, Adw, Gio
# module import
from .utils import create_toast,check_internet_connection
@@ -107,26 +107,27 @@ def show_loader(self):
return
container_loader = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
- container_loader.set_margin_top(200)
+ container_loader.set_margin_top(250)
container_loader.set_margin_bottom(300)
+
# Create loader
loader = Gtk.Spinner()
loader.set_margin_top(50)
loader.set_margin_bottom(50)
+ loader.set_size_request(120, 120)
+
loader.set_css_classes(['loader'])
container_loader.append(loader)
loader_label = Gtk.Label(label=f"Getting Weather Data")
- loader_label.set_css_classes(["text-1", "bold-2"])
+ loader_label.set_css_classes(["text-2a", "bold-2"])
container_loader.append(loader_label)
loader.start()
- # loader = Gtk.Label(label=f"Loading…")
- # loader.set_css_classes(["text-1", "bold-2"])
- loader.set_hexpand(True)
- loader.set_vexpand(True)
+ # loader.set_hexpand(True)
+ # loader.set_vexpand(True)
self.main_stack.add_named(container_loader, "loader")
self.main_stack.set_visible_child_name("loader")
@@ -211,8 +212,6 @@ def get_weather(self,reload_type=None,title = ""):
self.settings.reset('added-cities')
self.settings.reset('selected-city')
-
-
child = self.main_stack.get_child_by_name('main_grid')
if child is not None:
self.main_stack.remove(child)
@@ -317,7 +316,6 @@ def _refresh_weather(self,widget):
thread.start()
-
# ============= Menu buttom methods ==============
def _on_about_clicked(self, *args, **kwargs ):
AboutWindow(application)
diff --git a/src/windowAbout.py b/src/windowAbout.py
index 654d89f..8188a8c 100644
--- a/src/windowAbout.py
+++ b/src/windowAbout.py
@@ -5,7 +5,7 @@
def AboutWindow(parent,*args):
dialog = Adw.AboutWindow.new()
- dialog.set_application_name(_("Weather"))
+ dialog.set_application_name("Weather")
dialog.set_application_icon("io.github.amit9838.weather")
dialog.set_version("1.0.1")
dialog.set_developer_name("Amit Chaudhary")
@@ -14,7 +14,7 @@ def AboutWindow(parent,*args):
dialog.set_website("https://amit9838.github.io/weather/")
dialog.set_issue_url("https://github.com/amit9838/weather/issues")
# dialog.add_credit_section("Contributors", ["name url"])
- dialog.set_copyright(_("Copyright © 2023 Weather Developers"))
+ dialog.set_copyright(_("Copyright © 2024 Weather Developers"))
dialog.set_developers(["Amit Chaudhary"])
# Translators: Please enter your credits here. (format: "Name https://example.com" or "Name
", no quotes)
dialog.set_translator_credits(_("translator_credits"))
diff --git a/src/windowLocations.py b/src/windowLocations.py
index 1b8bde7..25cceae 100644
--- a/src/windowLocations.py
+++ b/src/windowLocations.py
@@ -4,7 +4,7 @@
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
-from gi.repository import Gtk, Adw,Gio,GLib
+from gi.repository import Gtk, Adw, GLib
from .utils import create_toast
from .backendFindCity import find_city
diff --git a/website/index.html b/website/index.html
index 92e7dd9..e851528 100644
--- a/website/index.html
+++ b/website/index.html
@@ -57,19 +57,23 @@