diff options
-rw-r--r-- | include/datetime/utils.h | 5 | ||||
-rw-r--r-- | src/utils.cpp | 89 | ||||
-rw-r--r-- | tests/state-fixture.h | 1 | ||||
-rw-r--r-- | tests/test-utils.cc | 79 |
4 files changed, 82 insertions, 92 deletions
diff --git a/include/datetime/utils.h b/include/datetime/utils.h index fbc80d7..10e881f 100644 --- a/include/datetime/utils.h +++ b/include/datetime/utils.h @@ -34,9 +34,12 @@ void split_settings_location (const char * location, char ** zone, char ** name); -gchar * get_current_zone_name (const char * location, +gchar * get_timezone_name (const char * timezone, GSettings * settings); +gchar * get_beautified_timezone_name (const char * timezone, + const char * saved_location); + gchar * generate_full_format_string_at_time (GDateTime * now, GDateTime * time); diff --git a/src/utils.cpp b/src/utils.cpp index acd9796..bef8c2e 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -25,10 +25,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <datetime/clock.h> #include <datetime/clock-mock.h> #include <datetime/formatter.h> -#include <datetime/settings-shared.h> +#include <datetime/settings-live.h> -#include <glib/gi18n-lib.h> -#include <gio/gio.h> +#include <glib.h> #include <locale.h> #include <langinfo.h> @@ -53,16 +52,15 @@ void split_settings_location(const gchar* location, gchar** zone, gchar** name) { auto location_dup = g_strdup(location); - g_strstrip(location_dup); + if(location_dup != nullptr) + g_strstrip(location_dup); gchar* first; - if((first = strchr(location_dup, ' '))) + if(location_dup && (first = strchr(location_dup, ' '))) *first = '\0'; if(zone) - { *zone = location_dup; - } if(name != nullptr) { @@ -72,7 +70,7 @@ split_settings_location(const gchar* location, gchar** zone, gchar** name) { *name = g_strdup(after); } - else // make the name from zone + else if (location_dup) // make the name from zone { gchar * chr = strrchr(location_dup, '/'); after = g_strdup(chr ? chr + 1 : location_dup); @@ -84,54 +82,73 @@ split_settings_location(const gchar* location, gchar** zone, gchar** name) *name = after; } + else + { + *name = nullptr; + } } } +/** + * Our Locations come from two places: (1) direct user input and (2) ones + * guessed by the system, such as from geoclue or timedate1. + * + * Since the latter only have a timezone (eg, "America/Chicago") and the + * former have a descriptive name provided by the end user (eg, + * "America/Chicago Oklahoma City"), this function tries to make a + * more human-readable name by using the user-provided name if the guessed + * timezone matches the last one the user manually clicked on. + * + * In the example above, this allows the menuitem for the system-guessed + * timezone ("America/Chicago") to read "Oklahoma City" after the user clicks + * on the "Oklahoma City" menuitem. + */ gchar* -get_current_zone_name(const gchar* location, GSettings* settings) +get_beautified_timezone_name(const char* timezone, const char* saved_location) { - gchar* new_zone; - gchar* new_name; - split_settings_location(location, &new_zone, &new_name); - - auto tz_name = g_settings_get_string(settings, SETTINGS_TIMEZONE_NAME_S); - gchar* old_zone; - gchar* old_name; - split_settings_location(tz_name, &old_zone, &old_name); - g_free(tz_name); + gchar* zone; + gchar* name; + split_settings_location(timezone, &zone, &name); - /* new_name is always just a sanitized version of a timezone. - old_name is potentially a saved "pretty" version of a timezone name from - geonames. So we prefer to use it if available and the zones match. */ + gchar* saved_zone; + gchar* saved_name; + split_settings_location(saved_location, &saved_zone, &saved_name); gchar* rv; - if (g_strcmp0(old_zone, new_zone) == 0) + if (g_strcmp0(zone, saved_zone) == 0) { - rv = old_name; - old_name = nullptr; + rv = saved_name; + saved_name = nullptr; } else { - rv = new_name; - new_name = nullptr; + rv = name; + name = nullptr; } - g_free(new_zone); - g_free(old_zone); - g_free(new_name); - g_free(old_name); + g_free(zone); + g_free(name); + g_free(saved_zone); + g_free(saved_name); return rv; } -gchar* generate_full_format_string_at_time(GDateTime* now, GDateTime* then) +gchar* +get_timezone_name(const gchar* timezone, GSettings* settings) { - using unity::indicator::datetime::Clock; - using unity::indicator::datetime::DateTime; - using unity::indicator::datetime::MockClock; - using unity::indicator::datetime::DesktopFormatter; + auto saved_location = g_settings_get_string(settings, SETTINGS_TIMEZONE_NAME_S); + auto rv = get_beautified_timezone_name(timezone, saved_location); + g_free(saved_location); + return rv; +} +using namespace unity::indicator::datetime; + +gchar* generate_full_format_string_at_time(GDateTime* now, GDateTime* then) +{ std::shared_ptr<Clock> clock(new MockClock(DateTime(now))); - DesktopFormatter formatter(clock); + std::shared_ptr<Settings> settings(new LiveSettings); + DesktopFormatter formatter(clock, settings); return g_strdup(formatter.getRelativeFormat(then).c_str()); } diff --git a/tests/state-fixture.h b/tests/state-fixture.h index 0286ea9..3c6ecd5 100644 --- a/tests/state-fixture.h +++ b/tests/state-fixture.h @@ -50,6 +50,7 @@ protected: const DateTime now = DateTime::NowLocal(); m_clock.reset(new MockClock(now)); m_state.reset(new State); + m_state->settings.reset(new Settings); m_state->timezones.reset(new Timezones); m_state->clock = std::dynamic_pointer_cast<Clock>(m_clock); m_state->planner.reset(new MockPlanner); diff --git a/tests/test-utils.cc b/tests/test-utils.cc index 8246396..2fe6a2e 100644 --- a/tests/test-utils.cc +++ b/tests/test-utils.cc @@ -17,22 +17,16 @@ * Charles Kerr <charles.kerr@canonical.com> */ -#include <gtest/gtest.h> - -#include <glib-object.h> - -#include "utils.h" +#include <datetime/utils.h> -/*** -**** -***/ +#include <gtest/gtest.h> TEST(UtilsTest, SplitSettingsLocation) { struct { - const char * location; - const char * expected_zone; - const char * expected_name; + const char* location; + const char* expected_zone; + const char* expected_name; } test_cases[] = { { "America/Chicago Chicago", "America/Chicago", "Chicago" }, { "America/Chicago Oklahoma City", "America/Chicago", "Oklahoma City" }, @@ -43,63 +37,38 @@ TEST(UtilsTest, SplitSettingsLocation) { "UTC UTC", "UTC", "UTC" } }; - for(guint i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) + for(const auto& test_case : test_cases) { - char * zone = NULL; - char * name = NULL; + char * zone = nullptr; + char * name = nullptr; - split_settings_location(test_cases[i].location, &zone, &name); - ASSERT_STREQ(test_cases[i].expected_zone, zone); - ASSERT_STREQ(test_cases[i].expected_name, name); + split_settings_location(test_case.location, &zone, &name); + ASSERT_STREQ(test_case.expected_zone, zone); + ASSERT_STREQ(test_case.expected_name, name); g_free(zone); g_free(name); } } -/*** -**** -***/ - -#define EM_SPACE "\xE2\x80\x82" - -TEST(UtilsTest, GenerateTerseFormatString) +TEST(UtilsTest, BeautifulTimezoneName) { - auto arbitrary_day = g_date_time_new_local(2013, 6, 25, 12, 34, 56); - auto on_the_hour = g_date_time_new_local(2013, 6, 25, 12, 0, 0); - struct { - GDateTime * now; - GDateTime * time; - const char * expected_format_string; + const char* timezone; + const char* location; + const char* expected_name; } test_cases[] = { - { g_date_time_ref(arbitrary_day), g_date_time_ref(arbitrary_day), "%l:%M %p" }, /* identical time */ - { g_date_time_ref(arbitrary_day), g_date_time_add_hours(arbitrary_day,1), "%l:%M %p" }, /* later today */ - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,1), "Tomorrow" EM_SPACE "%l:%M %p" }, /* tomorrow */ - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,2), "%a" EM_SPACE "%l:%M %p" }, - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,6), "%a" EM_SPACE "%l:%M %p" }, - { g_date_time_ref(arbitrary_day), g_date_time_add_days(arbitrary_day,7), "%d %b" EM_SPACE "%l:%M %p" }, /* over one week away */ - - { g_date_time_ref(on_the_hour), g_date_time_ref(on_the_hour), "%l %p" }, /* identical time */ - { g_date_time_ref(on_the_hour), g_date_time_add_hours(on_the_hour,1), "%l %p" }, /* later today */ - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,1), "Tomorrow" EM_SPACE "%l %p" }, /* tomorrow */ - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,2), "%a" EM_SPACE "%l %p" }, - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,6), "%a" EM_SPACE "%l %p" }, - { g_date_time_ref(on_the_hour), g_date_time_add_days(on_the_hour,7), "%d %b" EM_SPACE "%l %p" }, /* over one week away */ + { "America/Chicago", NULL, "Chicago" }, + { "America/Chicago", "America/Chicago", "Chicago" }, + { "America/Chicago", "America/Chigago Chicago", "Chicago" }, + { "America/Chicago", "America/Chicago Oklahoma City", "Oklahoma City" }, + { "America/Chicago", "Europe/London London", "Chicago" } }; - for(guint i=0, n=G_N_ELEMENTS(test_cases); i<n; i++) + for(const auto& test_case : test_cases) { - auto format_string = generate_terse_format_string_at_time(test_cases[i].now, - test_cases[i].time); - - ASSERT_STREQ(test_cases[i].expected_format_string, format_string); - - g_free(format_string); - g_date_time_unref(test_cases[i].now); - g_date_time_unref(test_cases[i].time); + auto name = get_beautified_timezone_name(test_case.timezone, test_case.location); + EXPECT_STREQ(test_case.expected_name, name); + g_free(name); } - - g_date_time_unref(arbitrary_day); - g_date_time_unref(on_the_hour); } |