weather-service: Reorganize file
This commit is contained in:
+153
-176
@@ -109,20 +109,6 @@ struct _GcalWeatherService
|
|||||||
static void on_gweather_update_cb (GWeatherInfo *info,
|
static void on_gweather_update_cb (GWeatherInfo *info,
|
||||||
GcalWeatherService *self);
|
GcalWeatherService *self);
|
||||||
|
|
||||||
static void schedule_midnight (GcalWeatherService *self);
|
|
||||||
|
|
||||||
static void start_timer (GcalWeatherService *self);
|
|
||||||
|
|
||||||
static void stop_timer (GcalWeatherService *self);
|
|
||||||
|
|
||||||
static gboolean has_valid_weather_infos (GcalWeatherService *self);
|
|
||||||
|
|
||||||
static void update_weather (GcalWeatherService *self,
|
|
||||||
GWeatherInfo *info,
|
|
||||||
gboolean reuse_old_on_error);
|
|
||||||
|
|
||||||
static gssize get_normalized_icon_name_len (const gchar *str);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GcalWeatherService, gcal_weather_service, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (GcalWeatherService, gcal_weather_service, G_TYPE_OBJECT)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@@ -145,6 +131,31 @@ static guint signals[N_SIGNALS] = { 0 };
|
|||||||
* Auxiliary methods
|
* Auxiliary methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static gssize
|
||||||
|
get_normalized_icon_name_len (const gchar *str)
|
||||||
|
{
|
||||||
|
const gchar *suffix1 = "-symbolic";
|
||||||
|
const gssize suffix1_len = strlen (suffix1);
|
||||||
|
|
||||||
|
const gchar *suffix2 = "-night";
|
||||||
|
const gssize suffix2_len = strlen (suffix2);
|
||||||
|
|
||||||
|
gssize clean_len;
|
||||||
|
gssize str_len;
|
||||||
|
|
||||||
|
str_len = strlen (str);
|
||||||
|
|
||||||
|
clean_len = str_len - suffix1_len;
|
||||||
|
if (clean_len >= 0 && memcmp (suffix1, str + clean_len, suffix1_len) == 0)
|
||||||
|
str_len = clean_len;
|
||||||
|
|
||||||
|
clean_len = str_len - suffix2_len;
|
||||||
|
if (clean_len >= 0 && memcmp (suffix2, str + clean_len, suffix2_len) == 0)
|
||||||
|
str_len = clean_len;
|
||||||
|
|
||||||
|
return str_len;
|
||||||
|
}
|
||||||
|
|
||||||
static gchar*
|
static gchar*
|
||||||
get_normalized_icon_name (GWeatherInfo* wi,
|
get_normalized_icon_name (GWeatherInfo* wi,
|
||||||
gboolean is_night_icon)
|
gboolean is_night_icon)
|
||||||
@@ -193,6 +204,18 @@ get_normalized_icon_name (GWeatherInfo* wi,
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
has_valid_weather_infos (GcalWeatherService *self)
|
||||||
|
{
|
||||||
|
gint64 now;
|
||||||
|
|
||||||
|
if (self->gweather_info == NULL || self->weather_infos_upated < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
now = g_get_monotonic_time ();
|
||||||
|
return (now - self->weather_infos_upated) / 1000000 <= self->valid_timespan;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_timeout_interval (GcalWeatherService *self)
|
update_timeout_interval (GcalWeatherService *self)
|
||||||
{
|
{
|
||||||
@@ -257,31 +280,6 @@ stop_timer (GcalWeatherService *self)
|
|||||||
gcal_timer_stop (self->midnight_timer);
|
gcal_timer_stop (self->midnight_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gssize
|
|
||||||
get_normalized_icon_name_len (const gchar *str)
|
|
||||||
{
|
|
||||||
const gchar *suffix1 = "-symbolic";
|
|
||||||
const gssize suffix1_len = strlen (suffix1);
|
|
||||||
|
|
||||||
const gchar *suffix2 = "-night";
|
|
||||||
const gssize suffix2_len = strlen (suffix2);
|
|
||||||
|
|
||||||
gssize clean_len;
|
|
||||||
gssize str_len;
|
|
||||||
|
|
||||||
str_len = strlen (str);
|
|
||||||
|
|
||||||
clean_len = str_len - suffix1_len;
|
|
||||||
if (clean_len >= 0 && memcmp (suffix1, str + clean_len, suffix1_len) == 0)
|
|
||||||
str_len = clean_len;
|
|
||||||
|
|
||||||
clean_len = str_len - suffix2_len;
|
|
||||||
if (clean_len >= 0 && memcmp (suffix2, str + clean_len, suffix2_len) == 0)
|
|
||||||
str_len = clean_len;
|
|
||||||
|
|
||||||
return str_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
get_icon_name_sortkey (const gchar *icon_name,
|
get_icon_name_sortkey (const gchar *icon_name,
|
||||||
gboolean *supports_night_icon)
|
gboolean *supports_night_icon)
|
||||||
@@ -469,79 +467,6 @@ compute_weather_info_data (GSList *samples,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
update_location (GcalWeatherService *self,
|
|
||||||
GWeatherLocation *location)
|
|
||||||
{
|
|
||||||
if (gcal_timer_is_running (self->duration_timer))
|
|
||||||
stop_timer (self);
|
|
||||||
|
|
||||||
if (self->gweather_info != NULL)
|
|
||||||
{
|
|
||||||
g_signal_handlers_disconnect_by_data (self->gweather_info, self);
|
|
||||||
g_clear_object (&self->gweather_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!location)
|
|
||||||
{
|
|
||||||
g_debug ("Could not retrieve current location");
|
|
||||||
update_weather (self, NULL, FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_debug ("Got new weather service location: '%s'",
|
|
||||||
!location ? "<null>" : gweather_location_get_name (location));
|
|
||||||
|
|
||||||
self->gweather_info = gweather_info_new (location);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: We do not get detailed infos for GWEATHER_PROVIDER_ALL.
|
|
||||||
* This combination works fine, though. We should open a bug / investigate
|
|
||||||
* what is going on.
|
|
||||||
*/
|
|
||||||
gweather_info_set_enabled_providers (self->gweather_info, GWEATHER_PROVIDER_METAR | GWEATHER_PROVIDER_OWM | GWEATHER_PROVIDER_YR_NO);
|
|
||||||
g_signal_connect_object (self->gweather_info, "updated", (GCallback) on_gweather_update_cb, self, 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* gweather_info_update might or might not trigger a
|
|
||||||
* GWeatherInfo::update() signal. Therefore, we have to
|
|
||||||
* remove weather information before querying new one.
|
|
||||||
* This might result in icon flickering on screen.
|
|
||||||
* We probably want to introduce a "unknown" or "loading"
|
|
||||||
* state in gweather-info to soften the effect.
|
|
||||||
*/
|
|
||||||
update_weather (self, NULL, FALSE);
|
|
||||||
gweather_info_update (self->gweather_info);
|
|
||||||
|
|
||||||
start_timer (self);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_gclue_location (GcalWeatherService *self,
|
|
||||||
GClueLocation *location)
|
|
||||||
{
|
|
||||||
GWeatherLocation *wlocation = NULL; /* owned */
|
|
||||||
|
|
||||||
if (location)
|
|
||||||
{
|
|
||||||
GWeatherLocation *wworld; /* unowned */
|
|
||||||
gdouble latitude;
|
|
||||||
gdouble longitude;
|
|
||||||
|
|
||||||
latitude = gclue_location_get_latitude (location);
|
|
||||||
longitude = gclue_location_get_longitude (location);
|
|
||||||
|
|
||||||
/* nearest-city works more closely to gnome weather. */
|
|
||||||
wworld = gweather_location_get_world ();
|
|
||||||
wlocation = gweather_location_find_nearest_city (wworld, latitude, longitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_location (self, wlocation);
|
|
||||||
|
|
||||||
g_clear_pointer (&wlocation, gweather_location_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GPtrArray*
|
static GPtrArray*
|
||||||
preprocess_gweather_reports (GcalWeatherService *self,
|
preprocess_gweather_reports (GcalWeatherService *self,
|
||||||
GSList *samples)
|
GSList *samples)
|
||||||
@@ -645,6 +570,122 @@ preprocess_gweather_reports (GcalWeatherService *self,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_weather (GcalWeatherService *self,
|
||||||
|
GWeatherInfo *info,
|
||||||
|
gboolean reuse_old_on_error)
|
||||||
|
{
|
||||||
|
GSList *gwforecast = NULL; /* unowned */
|
||||||
|
|
||||||
|
/* Compute a list of newly received weather infos. */
|
||||||
|
if (!info)
|
||||||
|
{
|
||||||
|
g_debug ("Could not retrieve valid weather");
|
||||||
|
}
|
||||||
|
else if (gweather_info_is_valid (info))
|
||||||
|
{
|
||||||
|
g_debug ("Received valid weather information");
|
||||||
|
gwforecast = gweather_info_get_forecast_list (info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_autofree gchar* location_name = gweather_info_get_location_name (info);
|
||||||
|
g_debug ("Could not retrieve valid weather for location '%s'", location_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gwforecast && self->weather_infos_upated >= 0)
|
||||||
|
{
|
||||||
|
if (!reuse_old_on_error || !has_valid_weather_infos (self))
|
||||||
|
{
|
||||||
|
g_clear_pointer (&self->weather_infos, g_ptr_array_unref);
|
||||||
|
self->weather_infos_upated = -1;
|
||||||
|
|
||||||
|
g_signal_emit (self, signals[SIG_WEATHER_CHANGED], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gwforecast)
|
||||||
|
{
|
||||||
|
g_clear_pointer (&self->weather_infos, g_ptr_array_unref);
|
||||||
|
self->weather_infos = preprocess_gweather_reports (self, gwforecast);
|
||||||
|
self->weather_infos_upated = g_get_monotonic_time ();
|
||||||
|
|
||||||
|
g_signal_emit (self, signals[SIG_WEATHER_CHANGED], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_location (GcalWeatherService *self,
|
||||||
|
GWeatherLocation *location)
|
||||||
|
{
|
||||||
|
if (gcal_timer_is_running (self->duration_timer))
|
||||||
|
stop_timer (self);
|
||||||
|
|
||||||
|
if (self->gweather_info != NULL)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_data (self->gweather_info, self);
|
||||||
|
g_clear_object (&self->gweather_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!location)
|
||||||
|
{
|
||||||
|
g_debug ("Could not retrieve current location");
|
||||||
|
update_weather (self, NULL, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_debug ("Got new weather service location: '%s'",
|
||||||
|
!location ? "<null>" : gweather_location_get_name (location));
|
||||||
|
|
||||||
|
self->gweather_info = gweather_info_new (location);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: We do not get detailed infos for GWEATHER_PROVIDER_ALL.
|
||||||
|
* This combination works fine, though. We should open a bug / investigate
|
||||||
|
* what is going on.
|
||||||
|
*/
|
||||||
|
gweather_info_set_enabled_providers (self->gweather_info, GWEATHER_PROVIDER_METAR | GWEATHER_PROVIDER_OWM | GWEATHER_PROVIDER_YR_NO);
|
||||||
|
g_signal_connect_object (self->gweather_info, "updated", (GCallback) on_gweather_update_cb, self, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gweather_info_update might or might not trigger a
|
||||||
|
* GWeatherInfo::update() signal. Therefore, we have to
|
||||||
|
* remove weather information before querying new one.
|
||||||
|
* This might result in icon flickering on screen.
|
||||||
|
* We probably want to introduce a "unknown" or "loading"
|
||||||
|
* state in gweather-info to soften the effect.
|
||||||
|
*/
|
||||||
|
update_weather (self, NULL, FALSE);
|
||||||
|
gweather_info_update (self->gweather_info);
|
||||||
|
|
||||||
|
start_timer (self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_gclue_location (GcalWeatherService *self,
|
||||||
|
GClueLocation *location)
|
||||||
|
{
|
||||||
|
GWeatherLocation *wlocation = NULL; /* owned */
|
||||||
|
|
||||||
|
if (location)
|
||||||
|
{
|
||||||
|
GWeatherLocation *wworld; /* unowned */
|
||||||
|
gdouble latitude;
|
||||||
|
gdouble longitude;
|
||||||
|
|
||||||
|
latitude = gclue_location_get_latitude (location);
|
||||||
|
longitude = gclue_location_get_longitude (location);
|
||||||
|
|
||||||
|
/* nearest-city works more closely to gnome weather. */
|
||||||
|
wworld = gweather_location_get_world ();
|
||||||
|
wlocation = gweather_location_find_nearest_city (wworld, latitude, longitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
update_location (self, wlocation);
|
||||||
|
|
||||||
|
g_clear_pointer (&wlocation, gweather_location_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callbacks
|
* Callbacks
|
||||||
@@ -804,70 +845,6 @@ gwc2str (GWeatherInfo *gwi)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static gboolean
|
|
||||||
has_valid_weather_infos (GcalWeatherService *self)
|
|
||||||
{
|
|
||||||
gint64 now;
|
|
||||||
|
|
||||||
if (self->gweather_info == NULL || self->weather_infos_upated < 0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
now = g_get_monotonic_time ();
|
|
||||||
return (now - self->weather_infos_upated) / 1000000 <= self->valid_timespan;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update_weather:
|
|
||||||
* @self: A #GcalWeatherService instance.
|
|
||||||
* @info: (nullable): Newly received weather information or %NULL.
|
|
||||||
* @reuse_old_on_error: Whether to re-use old but not outdated weather
|
|
||||||
* information in case we could not fetch new data.
|
|
||||||
*
|
|
||||||
* Retrieves weather information for @location and triggers
|
|
||||||
* #GcalWeatherService::weather-changed.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
update_weather (GcalWeatherService *self,
|
|
||||||
GWeatherInfo *info,
|
|
||||||
gboolean reuse_old_on_error)
|
|
||||||
{
|
|
||||||
GSList *gwforecast = NULL; /* unowned */
|
|
||||||
|
|
||||||
/* Compute a list of newly received weather infos. */
|
|
||||||
if (!info)
|
|
||||||
{
|
|
||||||
g_debug ("Could not retrieve valid weather");
|
|
||||||
}
|
|
||||||
else if (gweather_info_is_valid (info))
|
|
||||||
{
|
|
||||||
g_debug ("Received valid weather information");
|
|
||||||
gwforecast = gweather_info_get_forecast_list (info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_autofree gchar* location_name = gweather_info_get_location_name (info);
|
|
||||||
g_debug ("Could not retrieve valid weather for location '%s'", location_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gwforecast && self->weather_infos_upated >= 0)
|
|
||||||
{
|
|
||||||
if (!reuse_old_on_error || !has_valid_weather_infos (self))
|
|
||||||
{
|
|
||||||
g_clear_pointer (&self->weather_infos, g_ptr_array_unref);
|
|
||||||
self->weather_infos_upated = -1;
|
|
||||||
|
|
||||||
g_signal_emit (self, signals[SIG_WEATHER_CHANGED], 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (gwforecast)
|
|
||||||
{
|
|
||||||
g_clear_pointer (&self->weather_infos, g_ptr_array_unref);
|
|
||||||
self->weather_infos = preprocess_gweather_reports (self, gwforecast);
|
|
||||||
self->weather_infos_upated = g_get_monotonic_time ();
|
|
||||||
|
|
||||||
g_signal_emit (self, signals[SIG_WEATHER_CHANGED], 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GObject overrides
|
* GObject overrides
|
||||||
|
|||||||
Reference in New Issue
Block a user