libtimezonemap/0018-Improve-the-location-selected-when-setting-the-timez.patch
David Shea 51a02b6c80 Update the map data and improve behavior:
- Render the map directly from SVG (#1335158)
- Fix memory leaks in tz.c
- Fix an invalid memory access
- Do not modify TZ in the process environment
- Move all data files to /usr/share/libtimezonemap from .../libtimezonemap/ui
- Add extra city data so all timezone offsets are clickable
- Move Venezuela from -04:30 to -04:00
- Fix the conversion of points just west of 180 longitude
- Remove the out-of-date Olson map data
- Update the "backward" file
- Improve the location selected when setting the timezone by name (#1322648)
- Remove an extra line in the +10:00 layer
- Move Chile back an hour
2016-06-29 14:56:01 -04:00

158 lines
4.4 KiB
Diff

From 4c87463e3b663b413c3be899bb15891aa7f0ee43 Mon Sep 17 00:00:00 2001
From: David Shea <dshea@redhat.com>
Date: Tue, 28 Jun 2016 13:49:14 -0400
Subject: [PATCH 18/24] Improve the location selected when setting the timezone
by name.
When setting the timezone from a name (e.g., Australia/Brisbane), try to
find the city that matches the timezone name. That way, in our example,
the pin will appear on Brisbane and not just some random city in eastern
Australia.
In addition, when cc_timezone_map_set_timezone is called for an unknown
timezone, set the offset highlight based on glib's view of timezones
(since this may be a low-population timezone without city data) and
unset the location.
---
src/cc-timezone-map.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 100 insertions(+), 3 deletions(-)
diff --git a/src/cc-timezone-map.c b/src/cc-timezone-map.c
index 11b14ea..5e4c210 100644
--- a/src/cc-timezone-map.c
+++ b/src/cc-timezone-map.c
@@ -28,6 +28,7 @@
#include <math.h>
#include "tz.h"
#include <librsvg/rsvg.h>
+#include <string.h>
G_DEFINE_TYPE (CcTimezoneMap, cc_timezone_map, GTK_TYPE_WIDGET)
@@ -817,10 +818,42 @@ cc_timezone_map_set_timezone (CcTimezoneMap *map,
const gchar *timezone)
{
GPtrArray *locations;
+ GList *zone_locations = NULL;
+ GList *location_node = NULL;
guint i;
- char *real_tz;
+ const char *real_tz;
+ const char *tz_city_start;
+ char *tz_city;
+ char *tmp;
+ gboolean found_location = FALSE;
real_tz = g_hash_table_lookup (map->priv->alias_db, timezone);
+ if (!real_tz)
+ real_tz = timezone;
+
+ tz_city_start = strrchr (timezone, '/');
+ if (tz_city_start)
+ {
+ /* Move to the first character after the / */
+ tz_city_start++;
+ }
+ else
+ {
+ tz_city_start = real_tz;
+ }
+
+ tz_city = g_strdup(tz_city_start);
+
+ /* Replace the underscores with spaces */
+ tmp = tz_city;
+ while (*tmp != '\0')
+ {
+ if (*tmp == '_')
+ {
+ *tmp = ' ';
+ }
+ tmp++;
+ }
locations = tz_get_locations (map->priv->tzdb);
@@ -828,12 +861,76 @@ cc_timezone_map_set_timezone (CcTimezoneMap *map,
{
CcTimezoneLocation *loc = locations->pdata[i];
- if (!g_strcmp0 (cc_timezone_location_get_zone(loc), real_tz ? real_tz : timezone))
+ if (!g_strcmp0 (cc_timezone_location_get_zone (loc), real_tz))
{
- set_location (map, loc);
+ zone_locations = g_list_prepend (zone_locations, loc);
+ }
+ }
+
+ /* No location found. Use GLib to set the highlight. g_time_zone_new always
+ * returns a GTimeZone, so invalid zones will just be offset 0.
+ */
+ if (zone_locations == NULL)
+ {
+ CcTimezoneLocation *test_location = cc_timezone_location_new ();
+ gdouble offset;
+
+ cc_timezone_location_set_zone (test_location, real_tz);
+ offset = get_location_offset (test_location);
+ g_object_unref (test_location);
+
+ set_location (map, NULL);
+ cc_timezone_map_set_selected_offset (map, offset);
+
+ return;
+ }
+
+ /* Look for a location with a name that either starts or ends with the name
+ * of the zone
+ */
+ location_node = zone_locations;
+ while (location_node != NULL)
+ {
+ const gchar *name = cc_timezone_location_get_en_name (location_node->data);
+ if (!strncmp (name, tz_city, strlen (tz_city)) ||
+ ((strlen(name) > strlen(tz_city)) &&
+ !strncmp (name + (strlen(name) - strlen(tz_city)), tz_city, strlen (tz_city))))
+ {
+ set_location (map, location_node->data);
+ found_location = TRUE;
break;
}
+
+ location_node = location_node->next;
}
+
+ /* If that didn't work, try by state */
+ if (!found_location)
+ {
+ location_node = zone_locations;
+ while (location_node != NULL)
+ {
+ const gchar *state = cc_timezone_location_get_state (location_node->data);
+
+ if ((state != NULL) &&
+ !strncmp (state, tz_city, strlen (tz_city)))
+ {
+ set_location (map, location_node->data);
+ found_location = TRUE;
+ break;
+ }
+
+ location_node = location_node->next;
+ }
+ }
+
+ /* If nothing matched, just use the first location */
+ if (!found_location)
+ {
+ set_location (map, zone_locations->data);
+ }
+
+ g_list_free (zone_locations);
}
void
--
2.5.5