summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2021-11-09 17:35:38 +0000
committerEmmanuele Bassi <ebassi@gmail.com>2021-11-17 21:53:05 +0000
commitf588c3b32e0624e406f40559111a7d85f71ad948 (patch)
tree7f57149512ef395851fb3faeddbcacb5923359db
parent0452f94918b0d9f2698c89b8095cdadb3feb29b4 (diff)
downloadlibgweather-f588c3b32e0624e406f40559111a7d85f71ad948.tar.gz
Turn GWeatherLocation into a proper GObject
We want to make it easier to use GWeatherLocation inside data structures like GListModel implementations. It's also easier to use from language bindings, as now objects will have a clear life time.
-rw-r--r--libgweather/gweather-location.c293
-rw-r--r--libgweather/gweather-location.h4
-rw-r--r--libgweather/gweather-private.h6
-rw-r--r--libgweather/gweather-timezone.c4
-rw-r--r--libgweather/gweather-weather.c185
-rw-r--r--libgweather/tests/test_libgweather.c67
-rw-r--r--libgweather/tools/test_weather.c2
7 files changed, 317 insertions, 244 deletions
diff --git a/libgweather/gweather-location.c b/libgweather/gweather-location.c
index 4e2ef94..89f9693 100644
--- a/libgweather/gweather-location.c
+++ b/libgweather/gweather-location.c
@@ -25,28 +25,82 @@
* airport to a city, see also test_distance() */
#define AIRPORT_MAX_DISTANCE 100.0
+G_DEFINE_TYPE (GWeatherLocation, gweather_location, G_TYPE_OBJECT)
+
+static void
+gweather_location_finalize (GObject *gobject)
+{
+ GWeatherLocation *self = GWEATHER_LOCATION (gobject);
+
+ /* Remove weak reference from DB object; but only if it points to us.
+ * It may point elsewhere if we are an implicit nearest child. */
+ if (self->db && g_ptr_array_index (self->db->locations, self->db_idx) == self)
+ g_ptr_array_index (self->db->locations, self->db_idx) = NULL;
+
+ g_free (self->_english_name);
+ g_free (self->_local_name);
+ g_free (self->_local_sort_name);
+ g_free (self->_english_sort_name);
+ g_free (self->_country_code);
+ g_free (self->_station_code);
+
+ g_clear_pointer (&self->_timezone, gweather_timezone_unref);
+
+ G_OBJECT_CLASS (gweather_location_parent_class)->finalize (gobject);
+}
+
+static void
+gweather_location_dispose (GObject *gobject)
+{
+ GWeatherLocation *self = GWEATHER_LOCATION (gobject);
+
+ if (self->_children) {
+ for (int i = 0; self->_children[i]; i++) {
+ g_object_unref (self->_children[i]);
+ }
+ g_free (self->_children);
+ self->_children = NULL;
+ }
+
+ g_clear_object (&self->_parent);
+
+ G_OBJECT_CLASS (gweather_location_parent_class)->dispose (gobject);
+}
+
+static void
+gweather_location_class_init (GWeatherLocationClass *klass)
+{
+ G_OBJECT_CLASS (klass)->dispose = gweather_location_dispose;
+ G_OBJECT_CLASS (klass)->finalize = gweather_location_finalize;
+}
+
+static void
+gweather_location_init (GWeatherLocation *self)
+{
+ self->latitude = self->longitude = DBL_MAX;
+ self->db_idx = INVALID_IDX;
+ self->tz_hint_idx = INVALID_IDX;
+}
+
static inline GWeatherLocation *
_iter_up (GWeatherLocation *loc)
{
GWeatherLocation *tmp;
tmp = gweather_location_get_parent (loc);
- gweather_location_unref (loc);
+ g_object_unref (loc);
+
return tmp;
}
-#define ITER_UP(start, _p) for ((_p) = gweather_location_ref (start); (_p); (_p) = _iter_up (_p))
+#define ITER_UP(start, _p) for ((_p) = g_object_ref (start); (_p); (_p) = _iter_up (_p))
static GWeatherLocation *
location_new (GWeatherLocationLevel level)
{
GWeatherLocation *loc;
- loc = g_slice_new0 (GWeatherLocation);
- loc->latitude = loc->longitude = DBL_MAX;
+ loc = g_object_new (GWEATHER_TYPE_LOCATION, NULL);
loc->level = level;
- loc->ref_count = 1;
- loc->db_idx = INVALID_IDX;
- loc->tz_hint_idx = INVALID_IDX;
return loc;
}
@@ -69,7 +123,7 @@ location_ref_for_idx (GWeatherDb *db,
if (!nearest_of) {
loc = g_ptr_array_index (db->locations, idx);
if (loc) {
- return gweather_location_ref (loc);
+ return g_object_ref (loc);
}
}
@@ -132,7 +186,78 @@ _gweather_location_reset_world (void)
}
}
-G_DEFINE_BOXED_TYPE (GWeatherLocation, gweather_location, gweather_location_ref, gweather_location_unref)
+static gpointer
+ensure_world (gpointer dummy G_GNUC_UNUSED)
+{
+ g_autoptr (GError) error = NULL;
+ g_autofree char *filename = NULL;
+ g_autoptr (GMappedFile) map;
+ const char *locations_path;
+ time_t now;
+ struct tm tm;
+ GWeatherDb *db = NULL;
+
+ locations_path = g_getenv ("LIBGWEATHER_LOCATIONS_PATH");
+ if (locations_path != NULL) {
+ filename = g_strdup (locations_path);
+ if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
+ g_warning ("User specified database %s does not exist", filename);
+ g_clear_pointer (&filename, g_free);
+ }
+ }
+
+ if (filename == NULL) {
+ filename = g_build_filename (GWEATHER_BIN_LOCATION_DIR, "Locations.bin", NULL);
+ }
+
+ map = g_mapped_file_new (filename, FALSE, &error);
+ if (map == NULL) {
+ g_critical ("Failed to open database %s: %s", filename, error->message);
+ return NULL;
+ }
+
+ db = g_new0 (GWeatherDb, 1);
+ db->world = db_world_from_data (g_mapped_file_get_contents (map), g_mapped_file_get_length (map));
+ /* This is GWthDB01 */
+ if (db_world_get_magic (db->world) != 0x5747687442443130) {
+ g_free (db);
+ return NULL;
+ }
+
+ db->map = g_steal_pointer (&map);
+
+ db->locations_ref = db_world_get_locations (db->world);
+ db->timezones_ref = db_world_get_timezones (db->world);
+
+ db->locations = g_ptr_array_new ();
+ db->timezones = g_ptr_array_new ();
+
+ g_ptr_array_set_size (db->locations, db_arrayof_location_get_length (db->locations_ref));
+ g_ptr_array_set_size (db->timezones, db_world_timezones_get_length (db->timezones_ref));
+
+ /* Get timestamps for the start and end of this year.
+ * This is used to parse timezone information. */
+ now = time (NULL);
+ tm = *gmtime (&now);
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+ db->year_start = mktime (&tm);
+ tm.tm_year++;
+ db->year_end = mktime (&tm);
+
+ world_db = db;
+
+ return db;
+}
+
+static void
+gweather_location_ensure_world (void)
+{
+ static GOnce ensure_world_once = G_ONCE_INIT;
+
+ g_once (&ensure_world_once, ensure_world, NULL);
+}
/**
* gweather_location_get_world:
@@ -148,63 +273,7 @@ G_DEFINE_BOXED_TYPE (GWeatherLocation, gweather_location, gweather_location_ref,
GWeatherLocation *
gweather_location_get_world (void)
{
- if (world_db == NULL) {
- g_autoptr (GError) error = NULL;
- g_autofree char *filename = NULL;
- g_autoptr (GMappedFile) map;
- const char *locations_path;
- time_t now;
- struct tm tm;
-
- locations_path = g_getenv ("LIBGWEATHER_LOCATIONS_PATH");
- if (locations_path != NULL) {
- filename = g_strdup (locations_path);
- if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
- g_warning ("User specified database %s does not exist", filename);
- g_clear_pointer (&filename, g_free);
- }
- }
-
- if (filename == NULL) {
- filename = g_build_filename (GWEATHER_BIN_LOCATION_DIR, "Locations.bin", NULL);
- }
-
- map = g_mapped_file_new (filename, FALSE, &error);
- if (map == NULL) {
- g_critical ("Failed to open database %s: %s", filename, error->message);
- return NULL;
- }
-
- world_db = g_new0 (GWeatherDb, 1);
- world_db->world = db_world_from_data (g_mapped_file_get_contents (map), g_mapped_file_get_length (map));
- /* This is GWthDB01 */
- if (db_world_get_magic (world_db->world) != 0x5747687442443130) {
- g_free (world_db);
- return NULL;
- }
-
- world_db->map = g_steal_pointer (&map);
-
- world_db->locations_ref = db_world_get_locations (world_db->world);
- world_db->timezones_ref = db_world_get_timezones (world_db->world);
-
- world_db->locations = g_ptr_array_new ();
- world_db->timezones = g_ptr_array_new ();
-
- g_ptr_array_set_size (world_db->locations, db_arrayof_location_get_length (world_db->locations_ref));
- g_ptr_array_set_size (world_db->timezones, db_world_timezones_get_length (world_db->timezones_ref));
-
- /* Get timestamps for the start and end of this year.
- * This is used to parse timezone information. */
- now = time (NULL);
- tm = *gmtime (&now);
- tm.tm_mon = 0;
- tm.tm_mday = 1;
- tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
- world_db->year_start = mktime (&tm);
- tm.tm_year++;
- world_db->year_end = mktime (&tm);
- }
+ gweather_location_ensure_world ();
return location_ref_for_idx (world_db, 0, NULL);
}
@@ -213,18 +282,16 @@ gweather_location_get_world (void)
* gweather_location_ref:
* @loc: a location
*
- * Acquire a reference to the location.
+ * Acquires a reference to the location.
*
* Return value: (transfer full): the location, with an additional reference
+ *
+ * Deprecated: 4.0: Use [method@GObject.Object.ref] instead
**/
GWeatherLocation *
gweather_location_ref (GWeatherLocation *loc)
{
- g_return_val_if_fail (loc != NULL, NULL);
-
- loc->ref_count++;
-
- return loc;
+ return g_object_ref (loc);
}
/**
@@ -235,40 +302,13 @@ gweather_location_ref (GWeatherLocation *loc)
*
* If the reference was the last one held, this function will free
* the resources allocated by the location.
+ *
+ * Deprecated: 4.0: Use [method@GObject.Object.unref] instead
**/
void
gweather_location_unref (GWeatherLocation *loc)
{
- g_return_if_fail (loc != NULL);
-
- int i;
-
- if (--loc->ref_count)
- return;
-
- /* Remove weak reference from DB object; but only if it points to us.
- * It may point elsewhere if we are an implicit nearest child. */
- if (loc->db && g_ptr_array_index (loc->db->locations, loc->db_idx) == loc)
- g_ptr_array_index (loc->db->locations, loc->db_idx) = NULL;
-
- g_free (loc->_english_name);
- g_free (loc->_local_name);
- g_free (loc->_local_sort_name);
- g_free (loc->_english_sort_name);
- g_free (loc->_country_code);
- g_free (loc->_station_code);
-
- if (loc->_children) {
- for (i = 0; loc->_children[i]; i++) {
- gweather_location_unref (loc->_children[i]);
- }
- g_free (loc->_children);
- }
-
- g_clear_pointer (&loc->_parent, gweather_location_unref);
- g_clear_pointer (&loc->_timezone, gweather_timezone_unref);
-
- g_slice_free (GWeatherLocation, loc);
+ g_object_unref (loc);
}
/**
@@ -462,7 +502,7 @@ gweather_location_get_parent (GWeatherLocation *loc)
g_return_val_if_fail (loc != NULL, NULL);
if (loc->_parent)
- return gweather_location_ref (loc->_parent);
+ return g_object_ref (loc->_parent);
if (loc->level == GWEATHER_LOCATION_WORLD)
return NULL;
@@ -515,7 +555,7 @@ gweather_location_next_child (GWeatherLocation *loc,
if (loc->_children) {
if (child == NULL) {
if (loc->_children[0])
- return gweather_location_ref (loc->_children[0]);
+ return g_object_ref (loc->_children[0]);
else
return NULL;
}
@@ -523,7 +563,7 @@ gweather_location_next_child (GWeatherLocation *loc,
for (i = 0; loc->_children[i]; i++) {
if (loc->_children[i] == child) {
if (loc->_children[i + 1])
- return gweather_location_ref (loc->_children[i + 1]);
+ return g_object_ref (loc->_children[i + 1]);
else
return NULL;
}
@@ -653,8 +693,8 @@ find_nearest_city (GWeatherLocation *location,
data->longitude);
if (data->location == NULL || data->distance > distance) {
- g_clear_pointer (&data->location, gweather_location_unref);
- data->location = gweather_location_ref (location);
+ g_clear_object (&data->location);
+ data->location = g_object_ref (location);
data->distance = distance;
}
}
@@ -695,7 +735,7 @@ gweather_location_find_nearest_city (GWeatherLocation *loc,
if (G_UNLIKELY (loc == NULL))
return NULL;
} else {
- gweather_location_ref (loc);
+ g_object_ref (loc);
}
lat = lat * M_PI / 180.0;
@@ -709,7 +749,7 @@ gweather_location_find_nearest_city (GWeatherLocation *loc,
foreach_city (loc, (GFunc) find_nearest_city, &data, NULL, NULL, NULL);
if (loc != world)
- gweather_location_unref (loc);
+ g_object_unref (loc);
return data.location;
}
@@ -759,7 +799,7 @@ gweather_location_find_nearest_city_full (GWeatherLocation *loc,
if (G_UNLIKELY (world == NULL))
return NULL;
} else {
- gweather_location_ref (loc);
+ g_object_ref (loc);
}
lat = lat * M_PI / 180.0;
@@ -775,7 +815,7 @@ gweather_location_find_nearest_city_full (GWeatherLocation *loc,
destroy (user_data);
if (loc != world)
- gweather_location_unref (loc);
+ g_object_unref (loc);
return data.location;
}
@@ -808,7 +848,7 @@ _got_place (GObject *source_object,
foreach_city (info->location, (GFunc) find_nearest_city, &data, country_code, NULL, NULL);
- gweather_location_unref (info->location);
+ g_object_unref (info->location);
g_slice_free (ArgData, info);
if (data.location == NULL) {
@@ -821,7 +861,7 @@ _got_place (GObject *source_object,
data.latitude,
data.longitude);
- g_task_return_pointer (task, location, (GDestroyNotify) gweather_location_unref);
+ g_task_return_pointer (task, location, (GDestroyNotify) g_object_unref);
}
g_object_unref (task);
@@ -875,7 +915,7 @@ gweather_location_detect_nearest_city (GWeatherLocation *loc,
data->latitude = lat;
data->longitude = lon;
data->location = loc != NULL
- ? gweather_location_ref (loc)
+ ? g_object_ref (loc)
: g_steal_pointer (&world);
data->task = task;
@@ -883,8 +923,8 @@ gweather_location_detect_nearest_city (GWeatherLocation *loc,
}
/**
- * gweather_location_detect_nearest_location_finish:
- * @result:
+ * gweather_location_detect_nearest_city_finish:
+ * @result: the result of the asynchronous operation
* @error: Stores error if any occurs in retrieving the result
*
* Fetches the location from @result.
@@ -893,7 +933,8 @@ gweather_location_detect_nearest_city (GWeatherLocation *loc,
*/
GWeatherLocation *
-gweather_location_detect_nearest_city_finish (GAsyncResult *result, GError **error)
+gweather_location_detect_nearest_city_finish (GAsyncResult *result,
+ GError **error)
{
GTask *task;
@@ -1226,7 +1267,7 @@ _gweather_location_update_weather_location (GWeatherLocation *gloc,
start = first_child;
}
if (!start)
- start = gweather_location_ref (gloc);
+ start = g_object_ref (gloc);
ITER_UP (start, l) {
if (!code)
@@ -1413,7 +1454,7 @@ gweather_location_format_two_serialize (GWeatherLocation *location)
is_city = FALSE;
}
if (!real_loc)
- real_loc = gweather_location_ref (location);
+ real_loc = g_object_ref (location);
parent = gweather_location_get_parent (real_loc);
@@ -1508,7 +1549,7 @@ gweather_location_common_deserialize (GWeatherLocation *world,
if (found && (g_strcmp0 (name, gweather_location_get_english_name (found)) == 0 ||
g_strcmp0 (name, gweather_location_get_name (found)) == 0))
return g_steal_pointer (&found);
- g_clear_pointer (&found, gweather_location_unref);
+ g_clear_object (&found);
}
if (station_code[0] == '\0')
@@ -1576,9 +1617,9 @@ gweather_location_common_deserialize (GWeatherLocation *world,
if (name == NULL ||
g_str_equal (name, gweather_location_get_english_name (found)) ||
g_str_equal (name, gweather_location_get_name (found)))
- found = gweather_location_ref (found);
+ found = g_object_ref (found);
else
- found = _gweather_location_new_detached (gweather_location_ref (ws), name, TRUE, latitude, longitude);
+ found = _gweather_location_new_detached (g_object_ref (ws), name, TRUE, latitude, longitude);
return found;
}
@@ -1727,7 +1768,7 @@ gweather_location_deserialize (GWeatherLocation *world,
}
/**
- * gweather_location_new_detached:
+ * gweather_location_new_detached: (constructor)
* @name: the user visible location name
* @icao: (nullable): the ICAO code of the location
* @latitude: the latitude of the location
@@ -1735,6 +1776,8 @@ gweather_location_deserialize (GWeatherLocation *world,
*
* Construct a new location from the given data, supplementing
* any missing information from the static database.
+ *
+ * Returns: (transfer full): the newly created detached location
*/
GWeatherLocation *
gweather_location_new_detached (const char *name,
@@ -1743,7 +1786,6 @@ gweather_location_new_detached (const char *name,
gdouble longitude)
{
g_autoptr (GWeatherLocation) world = NULL;
- g_autoptr (GWeatherLocation) city = NULL;
g_return_val_if_fail (name != NULL, NULL);
@@ -1758,10 +1800,11 @@ gweather_location_new_detached (const char *name,
if (icao != NULL) {
return gweather_location_common_deserialize (world, name, icao, FALSE, TRUE, latitude, longitude, FALSE, 0, 0);
} else {
- city = gweather_location_find_nearest_city (world, latitude, longitude);
+ g_autoptr (GWeatherLocation) city = gweather_location_find_nearest_city (world, latitude, longitude);
latitude = DEGREES_TO_RADIANS (latitude);
longitude = DEGREES_TO_RADIANS (longitude);
+
return _gweather_location_new_detached (g_steal_pointer (&city), name, TRUE, latitude, longitude);
}
}
diff --git a/libgweather/gweather-location.h b/libgweather/gweather-location.h
index 8d3b057..0166025 100644
--- a/libgweather/gweather-location.h
+++ b/libgweather/gweather-location.h
@@ -85,7 +85,7 @@ typedef enum { /*< underscore_name=gweather_location_level >*/
#define GWEATHER_TYPE_LOCATION (gweather_location_get_type ())
GWEATHER_AVAILABLE_IN_ALL
-GType gweather_location_get_type (void);
+G_DECLARE_FINAL_TYPE (GWeatherLocation, gweather_location, GWEATHER, LOCATION, GObject)
GWEATHER_AVAILABLE_IN_ALL
GWeatherLocation * gweather_location_get_world (void);
@@ -94,8 +94,6 @@ GWeatherLocation * gweather_location_ref (GWeatherLocatio
GWEATHER_AVAILABLE_IN_ALL
void gweather_location_unref (GWeatherLocation *loc);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (GWeatherLocation, gweather_location_unref);
-
GWEATHER_AVAILABLE_IN_ALL
const char * gweather_location_get_name (GWeatherLocation *loc);
GWEATHER_AVAILABLE_IN_ALL
diff --git a/libgweather/gweather-private.h b/libgweather/gweather-private.h
index 68d5665..282112d 100644
--- a/libgweather/gweather-private.h
+++ b/libgweather/gweather-private.h
@@ -40,8 +40,10 @@ typedef struct {
} GWeatherDb;
struct _GWeatherLocation {
+ GObject parent_instance;
+
GWeatherDb *db;
- guint db_idx;
+ guint db_idx;
DbLocationRef ref;
/* Attributes with _ may be fetched/filled from the database on the fly */
@@ -66,8 +68,6 @@ struct _GWeatherLocation {
double longitude;
gboolean latlon_valid;
-
- int ref_count;
};
#define WEATHER_LOCATION_CODE_LEN 4
diff --git a/libgweather/gweather-timezone.c b/libgweather/gweather-timezone.c
index a75b82e..cd8f405 100644
--- a/libgweather/gweather-timezone.c
+++ b/libgweather/gweather-timezone.c
@@ -185,7 +185,7 @@ _gweather_timezone_ref_for_idx (GWeatherDb *db,
GWeatherTimezone *
gweather_timezone_get_by_tzid (const char *tzid)
{
- GWeatherLocation *world;
+ g_autoptr (GWeatherLocation) world = NULL;
GWeatherDb *db;
gsize idx;
@@ -194,7 +194,6 @@ gweather_timezone_get_by_tzid (const char *tzid)
/* TODO: Get the DB directly */
world = gweather_location_get_world ();
db = world->db;
- gweather_location_unref (world);
if (!db_world_timezones_lookup (db->timezones_ref, tzid, &idx, NULL))
return NULL;
@@ -216,6 +215,7 @@ gweather_timezone_ref (GWeatherTimezone *zone)
g_return_val_if_fail (zone != NULL, NULL);
zone->ref_count++;
+
return zone;
}
diff --git a/libgweather/gweather-weather.c b/libgweather/gweather-weather.c
index 6531d21..fd6cc41 100644
--- a/libgweather/gweather-weather.c
+++ b/libgweather/gweather-weather.c
@@ -61,6 +61,8 @@ enum
static guint gweather_info_signals[SIGNAL_LAST];
+static GParamSpec *gweather_info_pspecs[PROP_LAST];
+
G_DEFINE_TYPE (GWeatherInfo, gweather_info, G_TYPE_OBJECT);
void
@@ -766,10 +768,9 @@ gweather_info_finalize (GObject *object)
GWeatherInfo *info = GWEATHER_INFO (object);
_weather_location_free (&info->location);
- g_clear_object (&info->settings);
- if (info->glocation)
- gweather_location_unref (info->glocation);
+ g_clear_object (&info->settings);
+ g_clear_object (&info->glocation);
g_clear_pointer (&info->application_id, g_free);
g_clear_pointer (&info->contact_info, g_free);
@@ -2098,13 +2099,13 @@ gweather_info_set_location_internal (GWeatherInfo *info,
if (info->glocation == location)
return;
- if (info->glocation)
- gweather_location_unref (info->glocation);
+ if (info->glocation != NULL)
+ g_object_unref (info->glocation);
info->glocation = location;
- if (info->glocation) {
- gweather_location_ref (location);
+ if (info->glocation != NULL) {
+ g_object_ref (info->glocation);
} else {
g_autoptr (GWeatherLocation) world = NULL;
const gchar *station_code;
@@ -2122,8 +2123,7 @@ gweather_info_set_location_internal (GWeatherInfo *info,
if (info->glocation) {
_weather_location_free (&info->location);
- _gweather_location_update_weather_location (info->glocation,
- &info->location);
+ _gweather_location_update_weather_location (info->glocation, &info->location);
}
if (name) {
@@ -2144,11 +2144,12 @@ gweather_info_set_location_internal (GWeatherInfo *info,
/**
* gweather_info_set_location:
* @info: a #GWeatherInfo
- * @location: (allow-none): a location for which weather is desired
+ * @location: (nullable): a location for which weather is desired
*
- * Changes @info to report weather for @location.
- * Note that this will clear any forecast or current conditions from
- * @info, you must call gweather_info_update() to obtain the new data.
+ * Changes the location of the weather report.
+ *
+ * Note that this will clear any forecast or current conditions, and
+ * you must call [method@GWeather.Info.update] to obtain the new data.
*/
void
gweather_info_set_location (GWeatherInfo *info,
@@ -2205,7 +2206,8 @@ gweather_info_set_enabled_providers (GWeatherInfo *info,
info->providers = providers;
gweather_info_abort (info);
- g_object_notify (G_OBJECT (info), "enabled-providers");
+
+ g_object_notify_by_pspec (G_OBJECT (info), gweather_info_pspecs[PROP_ENABLED_PROVIDERS]);
}
/**
@@ -2310,7 +2312,7 @@ gweather_info_set_property (GObject *object,
switch (property_id) {
case PROP_LOCATION:
- gweather_info_set_location_internal (self, (GWeatherLocation *) g_value_get_boxed (value));
+ gweather_info_set_location_internal (self, g_value_get_object (value));
break;
case PROP_ENABLED_PROVIDERS:
gweather_info_set_enabled_providers (self, g_value_get_flags (value));
@@ -2336,7 +2338,7 @@ gweather_info_get_property (GObject *object,
switch (property_id) {
case PROP_LOCATION:
- g_value_set_boxed (value, self->glocation);
+ g_value_set_object (value, self->glocation);
break;
case PROP_ENABLED_PROVIDERS:
g_value_set_flags (value, self->providers);
@@ -2353,25 +2355,27 @@ gweather_info_get_property (GObject *object,
}
static void
-gweather_info_constructed (GObject *object)
+gweather_info_constructed (GObject *gobject)
{
- GWeatherInfo *info = GWEATHER_INFO (object);
- GApplication *app;
+ GWeatherInfo *self = GWEATHER_INFO (gobject);
- if (info->application_id != NULL)
- return;
- app = g_application_get_default ();
- if (!app)
- return;
+ /* Use the application id of the default GApplication instance as the
+ * fallback value
+ */
+ if (self->application_id == NULL) {
+ GApplication *app = g_application_get_default ();
- gweather_info_set_application_id (info,
- g_application_get_application_id (app));
+ if (app != NULL) {
+ gweather_info_set_application_id (self, g_application_get_application_id (app));
+ }
+ }
+
+ G_OBJECT_CLASS (gweather_info_parent_class)->constructed (gobject);
}
void
gweather_info_class_init (GWeatherInfoClass *klass)
{
- GParamSpec *pspec;
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = gweather_info_dispose;
@@ -2380,80 +2384,109 @@ gweather_info_class_init (GWeatherInfoClass *klass)
gobject_class->get_property = gweather_info_get_property;
gobject_class->constructed = gweather_info_constructed;
- pspec = g_param_spec_boxed ("location",
- "Location",
- "The location this info represents",
- GWEATHER_TYPE_LOCATION,
- G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
- g_object_class_install_property (gobject_class, PROP_LOCATION, pspec);
-
- pspec = g_param_spec_flags ("enabled-providers",
- "Enabled providers",
- "A bitmask of enabled weather service providers",
- GWEATHER_TYPE_PROVIDER,
- GWEATHER_PROVIDER_NONE,
- G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
- g_object_class_install_property (gobject_class, PROP_ENABLED_PROVIDERS, pspec);
-
- pspec = g_param_spec_string ("application-id",
- "Application ID",
- "An unique reverse-DNS application ID",
- NULL,
- G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
- g_object_class_install_property (gobject_class, PROP_APPLICATION_ID, pspec);
-
- pspec = g_param_spec_string ("contact-info",
- "Contact information",
- "An email address or contact form URL",
- NULL,
- G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
- g_object_class_install_property (gobject_class, PROP_CONTACT_INFO, pspec);
+ /**
+ * GWeatherInfo:location:
+ *
+ * The location of the weather information.
+ */
+ gweather_info_pspecs[PROP_LOCATION] =
+ g_param_spec_object ("location",
+ "Location",
+ "The location this info represents",
+ GWEATHER_TYPE_LOCATION,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+ /**
+ * GWeatherInfo:enabled-providers:
+ *
+ * The enabled weather providers.
+ */
+ gweather_info_pspecs[PROP_ENABLED_PROVIDERS] =
+ g_param_spec_flags ("enabled-providers",
+ "Enabled providers",
+ "A bitmask of enabled weather service providers",
+ GWEATHER_TYPE_PROVIDER,
+ GWEATHER_PROVIDER_NONE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+ /**
+ * GWeatherInfo:application-id:
+ *
+ * A unique identifier, typically in the form of reverse DNS notation,
+ * for the application that is querying the weather information.
+ *
+ * Weather providers require this information.
+ */
+ gweather_info_pspecs[PROP_APPLICATION_ID] =
+ g_param_spec_string ("application-id",
+ "Application ID",
+ "An unique reverse-DNS application ID",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+ /**
+ * GWeatherInfo:contact-info:
+ *
+ * An email address or any other contact form URL.
+ *
+ * Weather providers require this information.
+ */
+ gweather_info_pspecs[PROP_CONTACT_INFO] =
+ g_param_spec_string ("contact-info",
+ "Contact information",
+ "An email address or contact form URL",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE);
+
+ g_object_class_install_properties (gobject_class, PROP_LAST, gweather_info_pspecs);
/**
* GWeatherInfo::updated:
- * @object: the emitter of the signal.
+ * @object: the object that emitted the signal
*
* This signal is emitted after the initial fetch of the weather
* data from upstream services, and after every successful call
- * to @gweather_info_update().
+ * to [method@GWeather.Info.update].
*/
- gweather_info_signals[SIGNAL_UPDATED] = g_signal_new ("updated",
- GWEATHER_TYPE_INFO,
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, /* accumulator */
- NULL, /* accu_data */
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
+ gweather_info_signals[SIGNAL_UPDATED] =
+ g_signal_new (g_intern_static_string ("updated"),
+ GWEATHER_TYPE_INFO,
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL, /* accumulator */
+ NULL, /* accu_data */
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
_gweather_gettext_init ();
}
/**
* gweather_info_new:
- * @location: (allow-none): the desidered #GWeatherLocation (%NULL for default)
+ * @location: (nullable): the desidered location
*
- * Builds a new #GWeatherInfo that will provide weather information about
- * @location.
+ * Builds a new `GWeatherInfo` that will provide weather information about
+ * the given location.
*
- * Since version 40, this does not automatically call gweather_info_update().
- * gweather_info_update() must be called manually once all the necessary set up
- * has been made, such as setting the enabled providers.
+ * In order to retrieve the weather information, you will need to enable
+ * the desired providers and then call [method@GWeather.Info.update]. If
+ * you want to be notified of the completion of the weather information
+ * update, you should connect to the [signal@GWeather.Info::updated]
+ * signal before updating the `GWeatherInfo` instance.
*
- * Returns: (transfer full): a new #GWeatherInfo
+ * Returns: (transfer full): a new weather information instance
*/
GWeatherInfo *
gweather_info_new (GWeatherLocation *location)
{
- if (location != NULL)
- return g_object_new (GWEATHER_TYPE_INFO, "location", location, NULL);
- return g_object_new (GWEATHER_TYPE_INFO, NULL);
+ g_return_val_if_fail (location == NULL || GWEATHER_IS_LOCATION (location), NULL);
+
+ return g_object_new (GWEATHER_TYPE_INFO, "location", location, NULL);
}
GWeatherInfo *
_gweather_info_new_clone (GWeatherInfo *original)
{
+ g_return_val_if_fail (GWEATHER_IS_INFO (original), NULL);
+
return g_object_new (GWEATHER_TYPE_INFO,
"application-id",
original->application_id,
diff --git a/libgweather/tests/test_libgweather.c b/libgweather/tests/test_libgweather.c
index ece4851..c3a80e0 100644
--- a/libgweather/tests/test_libgweather.c
+++ b/libgweather/tests/test_libgweather.c
@@ -48,7 +48,7 @@ test_named_timezones (void)
g_assert_true (code[0] == '@');
}
- g_clear_pointer (&world, gweather_location_unref);
+ g_clear_object (&world);
_gweather_location_reset_world ();
}
@@ -126,7 +126,7 @@ test_named_timezones_deserialized (void)
list = get_list_from_configuration (world, CONFIGURATION, 3);
for (l = list; l != NULL; l = l->next)
- gweather_location_unref (l->data);
+ g_object_unref (l->data);
g_list_free (list);
list = get_list_from_configuration (world, CONFIGURATION, 3);
@@ -141,11 +141,11 @@ test_named_timezones_deserialized (void)
g_assert_nonnull (tzid);
gweather_location_get_level (loc);
- gweather_location_unref (loc);
+ g_object_unref (loc);
}
g_list_free (list);
- g_clear_pointer (&world, gweather_location_unref);
+ g_clear_object (&world);
/* test_timezones will clear the DB */
test_timezones ();
}
@@ -179,9 +179,9 @@ test_no_code_serialize (void)
g_assert_cmpstr (gweather_location_get_name (loc), ==, gweather_location_get_name (new_loc));
g_assert_true (gweather_location_equal (loc, new_loc));
- g_clear_pointer (&world, gweather_location_unref);
- g_clear_pointer (&loc, gweather_location_unref);
- g_clear_pointer (&new_loc, gweather_location_unref);
+ g_clear_object (&world);
+ g_clear_object (&loc);
+ g_clear_pointer (&new_loc, g_object_unref);
_gweather_location_reset_world ();
}
@@ -240,7 +240,7 @@ test_timezones (void)
test_timezones_children (world);
- g_clear_pointer (&world, gweather_location_unref);
+ g_clear_object (&world);
_gweather_location_reset_world ();
}
@@ -291,7 +291,7 @@ test_airport_distance_sanity (void)
if (g_test_failed ())
g_warning ("Maximum city to airport distance is %.1f km", max_distance);
- g_clear_pointer (&world, gweather_location_unref);
+ g_clear_object (&world);
_gweather_location_reset_world ();
}
@@ -448,7 +448,7 @@ test_metar_weather_stations (void)
g_hash_table_unref (stations_ht);
- g_clear_pointer (&world, gweather_location_unref);
+ g_clear_object (&world);
_gweather_location_reset_world ();
}
@@ -522,8 +522,8 @@ test_utc_sunset (void)
g_object_unref (info);
- g_clear_pointer (&world, gweather_location_unref);
- g_clear_pointer (&utc, gweather_location_unref);
+ g_clear_object (&world);
+ g_clear_object (&utc);
_gweather_location_reset_world ();
}
@@ -577,10 +577,10 @@ test_bad_duplicate_weather_stations_children (GWeatherLocation *location,
stations = g_hash_table_lookup (stations_ht, code);
if (!stations) {
- stations = g_ptr_array_new_with_free_func ((GDestroyNotify) gweather_location_unref);
+ stations = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
g_hash_table_insert (stations_ht, g_strdup (code), stations);
}
- g_ptr_array_add (stations, gweather_location_ref (child));
+ g_ptr_array_add (stations, g_object_ref (child));
} else {
test_bad_duplicate_weather_stations_children (child, stations_ht);
}
@@ -605,7 +605,7 @@ test_bad_duplicate_weather_stations (void)
g_hash_table_unref (stations_ht);
g_unsetenv ("LIBGWEATHER_LOCATIONS_NO_NEAREST");
- g_clear_pointer (&world, gweather_location_unref);
+ g_clear_object (&world);
_gweather_location_reset_world ();
}
@@ -657,7 +657,7 @@ test_duplicate_weather_stations (void)
test_duplicate_weather_stations_children (world);
g_unsetenv ("LIBGWEATHER_LOCATIONS_NO_NEAREST");
- g_clear_pointer (&world, gweather_location_unref);
+ g_clear_object (&world);
_gweather_location_reset_world ();
}
@@ -683,8 +683,8 @@ test_location_names (void)
return;
}
- g_clear_pointer (&world, gweather_location_unref);
- g_clear_pointer (&brussels, gweather_location_unref);
+ g_clear_object (&world);
+ g_clear_object (&brussels);
_gweather_location_reset_world ();
world = gweather_location_get_world ();
@@ -695,11 +695,11 @@ test_location_names (void)
g_assert_cmpstr (gweather_location_get_name (brussels), ==, "Bruxelles");
g_assert_cmpstr (gweather_location_get_sort_name (brussels), ==, "bruxelles");
g_assert_cmpstr (gweather_location_get_english_name (brussels), ==, "Brussels");
- gweather_location_unref (brussels);
+ g_clear_object (&brussels);
+
+ g_clear_object (&world);
setlocale (LC_ALL, old_locale);
- g_clear_pointer (&world, gweather_location_unref);
- g_clear_pointer (&brussels, gweather_location_unref);
_gweather_location_reset_world ();
}
@@ -715,7 +715,7 @@ find_loc_children (GWeatherLocation *location,
code = gweather_location_get_code (child);
if (g_strcmp0 (search_str, code) == 0) {
- *ret = gweather_location_ref (child);
+ *ret = g_object_ref (child);
return TRUE;
}
} else {
@@ -785,7 +785,7 @@ test_weather_loop_use_after_free (void)
gweather_info_update (info);
g_object_unref (info);
- gweather_location_unref (loc);
+ g_object_unref (loc);
g_timeout_add_seconds (5, stop_loop_cb, loop);
g_main_loop_run (loop);
@@ -801,31 +801,30 @@ test_walk_world (void)
next = gweather_location_get_world ();
while (next) {
/* Update cur pointer. */
- g_clear_pointer (&cur, gweather_location_unref);
+ g_clear_object (&cur);
+
cur = g_steal_pointer (&next);
visited += 1;
- g_assert_cmpint (cur->ref_count, ==, 1);
/* Select next item, which is in this order:
- * 1. The first child
- * 2. Walk up the parent tree and try to find a sibbling
- * Note that cur remains valid after the loop and points to the world
- * again.
- */
+ * 1. The first child
+ * 2. Walk up the parent tree and try to find a sibbling
+ * Note that cur remains valid after the loop and points to the world
+ * again.
+ */
if ((next = gweather_location_next_child (cur, NULL)))
continue;
while (TRUE) {
g_autoptr (GWeatherLocation) child = NULL;
+
/* Move cur to the parent, keeping the child as reference. */
child = g_steal_pointer (&cur);
cur = gweather_location_get_parent (child);
if (!cur)
break;
- g_assert_cmpint (cur->ref_count, ==, 1);
- g_assert_cmpint (child->ref_count, ==, 1);
- if ((next = gweather_location_next_child (cur, gweather_location_ref (child))))
+ if ((next = gweather_location_next_child (cur, g_object_ref (child))))
break;
}
}
@@ -838,7 +837,7 @@ test_walk_world (void)
* of DB entries. */
cur = gweather_location_get_world ();
g_assert_cmpint (visited, >, cur->db->locations->len);
- g_clear_pointer (&cur, gweather_location_unref);
+ g_clear_object (&cur);
/* noop, but asserts we did not leak */
_gweather_location_reset_world ();
diff --git a/libgweather/tools/test_weather.c b/libgweather/tools/test_weather.c
index 99dd187..569307a 100644
--- a/libgweather/tools/test_weather.c
+++ b/libgweather/tools/test_weather.c
@@ -24,7 +24,7 @@ find_loc_children (GWeatherLocation *location,
code = gweather_location_get_code (child);
if (g_strcmp0 (search_str, code) == 0) {
- *ret = gweather_location_ref (child);
+ *ret = g_object_ref (child);
return TRUE;
}
} else {