weather: Allow to set a fix location.

This commit is contained in:
Florian Brosch
2017-12-11 21:23:19 -02:00
committed by Georges Basile Stavracas Neto
parent 83bec27ad5
commit 17af30b19c
2 changed files with 101 additions and 61 deletions
+98 -60
View File
@@ -19,7 +19,6 @@
#define DESKTOP_FILE_NAME "org.gnome.Calendar" #define DESKTOP_FILE_NAME "org.gnome.Calendar"
#include <geocode-glib/geocode-glib.h> #include <geocode-glib/geocode-glib.h>
#include <libgweather/gweather.h>
#include <geoclue.h> #include <geoclue.h>
#include "gcal-weather-service.h" #include "gcal-weather-service.h"
@@ -63,6 +62,7 @@ struct _GcalWeatherService
/* weather: */ /* weather: */
GWeatherInfo *weather_info; /* owned, nullable */ GWeatherInfo *weather_info; /* owned, nullable */
guint max_days; guint max_days;
gboolean weather_service_running;
}; };
@@ -88,41 +88,44 @@ G_DEFINE_TYPE (GcalWeatherService, gcal_weather_service, G_TYPE_OBJECT)
/* Internal location API and callbacks: */ /* Internal location API and callbacks: */
static void gcal_weather_service_update_location (GcalWeatherService *self, static void gcal_weather_service_update_location (GcalWeatherService *self,
GClueLocation *location); GWeatherLocation *location);
static char* gcal_weather_service_get_location_name (GClueLocation *location); static void gcal_weather_service_update_gclue_location (GcalWeatherService *self,
GClueLocation *location);
static void on_gclue_simple_creation (GClueSimple *source, static char* gcal_weather_service_get_location_name (GClueLocation *location);
GAsyncResult *result,
GcalWeatherService *data);
static void on_gclue_location_changed (GClueLocation *location, static void on_gclue_simple_creation (GClueSimple *source,
GcalWeatherService *self); GAsyncResult *result,
GcalWeatherService *data);
static void on_gclue_client_activity_changed (GClueClient *client, static void on_gclue_location_changed (GClueLocation *location,
GcalWeatherService *self); GcalWeatherService *self);
static void on_gclue_client_stop (GClueClient *client, static void on_gclue_client_activity_changed (GClueClient *client,
GAsyncResult *res, GcalWeatherService *self);
GClueSimple *simple);
static void on_gclue_client_stop (GClueClient *client,
GAsyncResult *res,
GClueSimple *simple);
/* Internal Wweather API */ /* Internal Wweather API */
static void gcal_weather_service_set_max_days (GcalWeatherService *self, static void gcal_weather_service_set_max_days (GcalWeatherService *self,
guint days); guint days);
static void gcal_weather_service_update_weather (GWeatherInfo *info, static void gcal_weather_service_update_weather (GWeatherInfo *info,
GcalWeatherService *self); GcalWeatherService *self);
/* Internal weather update timer API and callbacks */ /* Internal weather update timer API and callbacks */
static void gcal_weather_service_set_check_interval (GcalWeatherService *self, static void gcal_weather_service_set_check_interval (GcalWeatherService *self,
guint check_interval); guint check_interval);
static void gcal_weather_service_timer_stop (GcalWeatherService *self); static void gcal_weather_service_timer_stop (GcalWeatherService *self);
static void gcal_weather_service_timer_start (GcalWeatherService *self); static void gcal_weather_service_timer_start (GcalWeatherService *self);
static gboolean on_timer_timeout (GcalWeatherService *self); static gboolean on_timer_timeout (GcalWeatherService *self);
G_END_DECLS G_END_DECLS
@@ -225,7 +228,7 @@ gcal_weather_service_class_init (GcalWeatherServiceClass *klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), g_object_class_install_property (G_OBJECT_CLASS (klass),
PROP_MAX_DAYS, PROP_MAX_DAYS,
g_param_spec_uint ("max-days", "max-days", "max-days", g_param_spec_uint ("max-days", "max-days", "max-days",
0, G_MAXUINT, 0, prop_flags)); 1, G_MAXUINT, 3, prop_flags));
/** /**
* GcalWeatherServiceClass:check-interval: * GcalWeatherServiceClass:check-interval:
* *
@@ -269,6 +272,7 @@ gcal_weather_service_init (GcalWeatherService *self)
self->location_service_running = FALSE; self->location_service_running = FALSE;
self->location_service = NULL; self->location_service = NULL;
self->weather_info = NULL; self->weather_info = NULL;
self->weather_service_running = FALSE;
self->max_days = 0; self->max_days = 0;
} }
@@ -281,16 +285,15 @@ gcal_weather_service_init (GcalWeatherService *self)
/** /**
* gcal_weather_service_update_location: * gcal_weather_service_update_location:
* @self: The #GcalWeatherService instance. * @self: The #GcalWeatherService instance.
* @location: (nullable) (element-type Gcal.WeatherInfo): The location we want weather information for. * @location: (nullable): The location we want weather information for.
* *
* Registers the location to retrieve weather information from. * Registers the location to retrieve weather information from.
*/ */
static void static void
gcal_weather_service_update_location (GcalWeatherService *self, gcal_weather_service_update_location (GcalWeatherService *self,
GClueLocation *location) GWeatherLocation *location)
{ {
g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self)); g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
g_return_if_fail (location == NULL || GCLUE_IS_LOCATION (location));
if (self->weather_info != NULL) if (self->weather_info != NULL)
{ {
@@ -305,35 +308,66 @@ gcal_weather_service_update_location (GcalWeatherService *self,
} }
else else
{ {
GWeatherLocation *wlocation; /* owned */ self->weather_info = gweather_info_new (location, GWEATHER_FORECAST_ZONE);
g_autofree gchar *loc_name = NULL;
gdouble latitude;
gdouble longitude;
loc_name = gcal_weather_service_get_location_name (location);
latitude = gclue_location_get_latitude (location);
longitude = gclue_location_get_longitude (location);
wlocation = gweather_location_new_detached (loc_name, NULL, latitude, longitude);
self->weather_info = gweather_info_new (wlocation, GWEATHER_FORECAST_ZONE);
gweather_info_set_enabled_providers (self->weather_info, GWEATHER_PROVIDER_ALL); gweather_info_set_enabled_providers (self->weather_info, GWEATHER_PROVIDER_ALL);
g_signal_connect (self->weather_info, "updated", (GCallback) gcal_weather_service_update_weather, self); g_signal_connect (self->weather_info, "updated", (GCallback) gcal_weather_service_update_weather, self);
gweather_info_update (self->weather_info); gweather_info_update (self->weather_info);
gcal_weather_service_timer_start (self); gcal_weather_service_timer_start (self);
gweather_location_unref (wlocation);
} }
} }
/**
* gcal_weather_service_update_gclue_location:
* @self: The #GcalWeatherService instance.
* @location: (nullable): The location we want weather information for.
*
* Registers the location to retrieve weather information from.
*/
static void
gcal_weather_service_update_gclue_location (GcalWeatherService *self,
GClueLocation *location)
{
GWeatherLocation *wlocation = NULL; /* owned */
g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
g_return_if_fail (location == NULL || GCLUE_IS_LOCATION (location));
if (location != NULL)
{
g_autofree gchar *loc_name = NULL;
loc_name = gcal_weather_service_get_location_name (location);
if (loc_name != NULL)
{
gdouble latitude;
gdouble longitude;
latitude = gclue_location_get_latitude (location);
longitude = gclue_location_get_longitude (location);
wlocation = gweather_location_new_detached (loc_name, NULL, latitude, longitude);
}
}
gcal_weather_service_update_location (self, wlocation);
if (wlocation != NULL)
gweather_location_unref (wlocation);
}
/* gcal_weather_service_get_location_name: /* gcal_weather_service_get_location_name:
* @location: A #GClueLocation to get the city name from. * @location: A #GClueLocation to get the city name from.
* *
* Queries the city name for the given location or %NULL. * Queries the city name for the given location or %NULL.
* *
* @Returns: (transfer full): City name or %NULL. * @Returns: (transfer full) (nullable): City name or %NULL.
*/ */
static char* static char*
gcal_weather_service_get_location_name (GClueLocation *location) gcal_weather_service_get_location_name (GClueLocation *location)
@@ -378,7 +412,6 @@ on_gclue_simple_creation (GClueSimple *_source,
g_return_if_fail (G_IS_ASYNC_RESULT (result)); g_return_if_fail (G_IS_ASYNC_RESULT (result));
g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self)); g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
g_return_if_fail (self->location_service_running);
/* make sure we do not touch self->location_service /* make sure we do not touch self->location_service
* if the current operation was cancelled. * if the current operation was cancelled.
@@ -407,8 +440,7 @@ on_gclue_simple_creation (GClueSimple *_source,
if (location != NULL) if (location != NULL)
{ {
gcal_weather_service_update_location (self, location); gcal_weather_service_update_gclue_location (self, location);
g_signal_connect_object (location, g_signal_connect_object (location,
"notify::location", "notify::location",
@@ -427,7 +459,6 @@ on_gclue_simple_creation (GClueSimple *_source,
} }
/* on_gclue_location_changed: /* on_gclue_location_changed:
* @location: #GClueLocation owned by @self * @location: #GClueLocation owned by @self
* @self: The #GcalWeatherService * @self: The #GcalWeatherService
@@ -440,9 +471,8 @@ on_gclue_location_changed (GClueLocation *location,
{ {
g_return_if_fail (GCLUE_IS_LOCATION (location)); g_return_if_fail (GCLUE_IS_LOCATION (location));
g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self)); g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
g_return_if_fail (self->location_service_running);
gcal_weather_service_update_location (self, location); gcal_weather_service_update_gclue_location (self, location);
} }
@@ -459,7 +489,6 @@ on_gclue_client_activity_changed (GClueClient *client,
{ {
g_return_if_fail (GCLUE_IS_CLIENT (client)); g_return_if_fail (GCLUE_IS_CLIENT (client));
g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self)); g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
g_return_if_fail (self->location_service_running);
/* Notify listeners about unknown locations: */ /* Notify listeners about unknown locations: */
gcal_weather_service_update_location (self, NULL); gcal_weather_service_update_location (self, NULL);
@@ -674,24 +703,25 @@ gcal_weather_service_new (guint max_days,
/** /**
* gcal_weather_service_run: * gcal_weather_service_run:
* @self: The #GcalWeatherService instance. * @self: The #GcalWeatherService instance.
* @location: (nullable): A fixed location or %NULL to use Gclue.
* *
* Starts to monitor location and weather changes. * Starts to monitor location and weather changes.
* Use ::weather-changed to catch responses. * Use ::weather-changed to catch responses.
*/ */
void void
gcal_weather_service_run (GcalWeatherService *self) gcal_weather_service_run (GcalWeatherService *self,
GWeatherLocation *location)
{ {
g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self)); g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
if (self->location_service_running) if (self->location_service_running || self->weather_service_running)
return ; gcal_weather_service_stop (self);
self->location_service_running = TRUE; if (location == NULL)
g_assert (self->location_service == NULL);
if (self->max_days > 0)
{ {
/* Start location and weather service: */
self->location_service_running = TRUE;
self->location_service_running = TRUE;
g_cancellable_cancel (self->location_cancellable); g_cancellable_cancel (self->location_cancellable);
g_cancellable_reset (self->location_cancellable); g_cancellable_reset (self->location_cancellable);
gclue_simple_new (DESKTOP_FILE_NAME, gclue_simple_new (DESKTOP_FILE_NAME,
@@ -700,6 +730,15 @@ gcal_weather_service_run (GcalWeatherService *self)
(GAsyncReadyCallback) on_gclue_simple_creation, (GAsyncReadyCallback) on_gclue_simple_creation,
g_object_ref (self)); g_object_ref (self));
} }
else
{
/* Use the given location to retrieve weather information: */
self->location_service_running = FALSE;
self->location_service_running = TRUE;
gcal_weather_service_update_location (self, location);
gcal_weather_service_timer_start (self);
}
} }
@@ -716,11 +755,11 @@ gcal_weather_service_stop (GcalWeatherService *self)
{ {
g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self)); g_return_if_fail (GCAL_IS_WEATHER_SERVICE (self));
if (!self->location_service_running) if (!self->location_service_running && !self->weather_service_running)
return ; return ;
self->location_service_running = FALSE; self->location_service_running = FALSE;
self->weather_service_running = FALSE;
gcal_weather_service_timer_stop (self); gcal_weather_service_timer_stop (self);
@@ -734,15 +773,14 @@ gcal_weather_service_stop (GcalWeatherService *self)
} }
else else
{ {
GClueClient *client; /* owned */ GClueClient *client; /* unowned */
client = gclue_simple_get_client (self->location_service); client = gclue_simple_get_client (self->location_service);
self->location_service = NULL;
gclue_client_call_stop (client, gclue_client_call_stop (client,
NULL, NULL,
(GAsyncReadyCallback) on_gclue_client_stop, (GAsyncReadyCallback) on_gclue_client_stop,
client); /* transfres ownership */ g_steal_pointer (&self->location_service));
} }
} }
+3 -1
View File
@@ -19,6 +19,7 @@
#ifndef GCAL_WEATHER_SERVICE_H #ifndef GCAL_WEATHER_SERVICE_H
#define GCAL_WEATHER_SERVICE_H #define GCAL_WEATHER_SERVICE_H
#include <libgweather/gweather.h>
#include <glib-object.h> #include <glib-object.h>
#include <glib.h> #include <glib.h>
@@ -32,7 +33,8 @@ G_DECLARE_FINAL_TYPE (GcalWeatherService, gcal_weather_service, GCAL, WEATHER_SE
GcalWeatherService* gcal_weather_service_new (guint max_days, GcalWeatherService* gcal_weather_service_new (guint max_days,
guint check_interval); guint check_interval);
void gcal_weather_service_run (GcalWeatherService *self); void gcal_weather_service_run (GcalWeatherService *self,
GWeatherLocation *location);
void gcal_weather_service_stop (GcalWeatherService *self); void gcal_weather_service_stop (GcalWeatherService *self);