diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2021-11-09 17:35:38 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gmail.com> | 2021-11-17 21:53:05 +0000 |
commit | f588c3b32e0624e406f40559111a7d85f71ad948 (patch) | |
tree | 7f57149512ef395851fb3faeddbcacb5923359db | |
parent | 0452f94918b0d9f2698c89b8095cdadb3feb29b4 (diff) | |
download | libgweather-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.c | 293 | ||||
-rw-r--r-- | libgweather/gweather-location.h | 4 | ||||
-rw-r--r-- | libgweather/gweather-private.h | 6 | ||||
-rw-r--r-- | libgweather/gweather-timezone.c | 4 | ||||
-rw-r--r-- | libgweather/gweather-weather.c | 185 | ||||
-rw-r--r-- | libgweather/tests/test_libgweather.c | 67 | ||||
-rw-r--r-- | libgweather/tools/test_weather.c | 2 |
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 { |