From 78d0a231c12c159d1130ec080efab472f59851af Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 16 Jan 2014 16:42:36 -0600 Subject: update DesktopFormatter class to use the "Settings" class instead of using GSettings directly. --- include/datetime/formatter.h | 19 +++-- src/formatter-desktop.cpp | 186 +++++++++++++++++-------------------------- src/formatter.cpp | 49 +++++------- tests/test-formatter.cc | 177 +++++++++++++++++++--------------------- 4 files changed, 186 insertions(+), 245 deletions(-) diff --git a/include/datetime/formatter.h b/include/datetime/formatter.h index 09ed035..d8736c7 100644 --- a/include/datetime/formatter.h +++ b/include/datetime/formatter.h @@ -23,8 +23,14 @@ #include #include +#include +#include + #include +#include +#include + namespace unity { namespace indicator { namespace datetime { @@ -109,13 +115,16 @@ private: class DesktopFormatter: public Formatter { public: - DesktopFormatter(const std::shared_ptr&); - ~DesktopFormatter(); + DesktopFormatter(const std::shared_ptr&, const std::shared_ptr&); private: - class Impl; - friend Impl; - std::unique_ptr p; + std::shared_ptr m_settings; + + void rebuildHeaderFormat(); + const gchar* getFullTimeFormatString() const; + std::string getHeaderLabelFormatString() const; + const gchar* getDateFormat(bool show_day, bool show_date, bool show_year) const; + }; diff --git a/src/formatter-desktop.cpp b/src/formatter-desktop.cpp index 3f942f4..5efdf8b 100644 --- a/src/formatter-desktop.cpp +++ b/src/formatter-desktop.cpp @@ -18,10 +18,6 @@ */ #include -#include - -#include -#include namespace unity { namespace indicator { @@ -31,80 +27,108 @@ namespace datetime { **** ***/ -class DesktopFormatter::Impl +namespace { -public: -Impl(DesktopFormatter * owner, const std::shared_ptr& clock): - m_owner(owner), - m_clock(clock), - m_settings(g_settings_new(SETTINGS_INTERFACE)) +std::string joinDateAndTimeFormatStrings(const char* date_string, + const char* time_string) { - const gchar * const keys[] = { "changed::" SETTINGS_SHOW_SECONDS_S, - "changed::" SETTINGS_TIME_FORMAT_S, - "changed::" SETTINGS_TIME_FORMAT_S, - "changed::" SETTINGS_CUSTOM_TIME_FORMAT_S, - "changed::" SETTINGS_SHOW_DAY_S, - "changed::" SETTINGS_SHOW_DATE_S, - "changed::" SETTINGS_SHOW_YEAR_S }; - for(const auto& key : keys) - g_signal_connect(m_settings, key, G_CALLBACK(onSettingsChanged), this); + std::string str; - rebuildHeaderFormat(); -} + if (date_string && time_string) + { + /* TRANSLATORS: This is a format string passed to strftime to + * combine the date and the time. The value of "%s\u2003%s" + * will result in a string like this in US English 12-hour time: + * 'Fri Jul 16 11:50 AM'. The space in between date and time is + * a Unicode en space (E28082 in UTF-8 hex). */ + str = date_string; + str += "\u2003"; + str += time_string; + } + else if (date_string) + { + str = date_string; + } + else // time_string + { + str = time_string; + } -~Impl() -{ - g_signal_handlers_disconnect_by_data(m_settings, this); - g_object_unref(m_settings); + return str; } +} // unnamed namespace -private: +/*** +**** +***/ -static void onSettingsChanged(GSettings * /*changed*/, - const gchar * /*key*/, - gpointer gself) +DesktopFormatter::DesktopFormatter(const std::shared_ptr& clock_in, + const std::shared_ptr& settings_in): + Formatter(clock_in), + m_settings(settings_in) { - static_cast(gself)->rebuildHeaderFormat(); + m_settings->show_day.changed().connect([this](bool){rebuildHeaderFormat();}); + m_settings->show_date.changed().connect([this](bool){rebuildHeaderFormat();}); + m_settings->show_year.changed().connect([this](bool){rebuildHeaderFormat();}); + m_settings->show_seconds.changed().connect([this](bool){rebuildHeaderFormat();}); + m_settings->time_format_mode.changed().connect([this](TimeFormatMode){rebuildHeaderFormat();}); + m_settings->custom_time_format.changed().connect([this](const std::string&){rebuildHeaderFormat();}); + + rebuildHeaderFormat(); } -void rebuildHeaderFormat() +void DesktopFormatter::rebuildHeaderFormat() { - auto fmt = getHeaderLabelFormatString(m_settings); - m_owner->headerFormat.set(fmt); - g_free(fmt); + headerFormat.set(getHeaderLabelFormatString()); } -private: - -gchar* getHeaderLabelFormatString(GSettings* s) const +std::string DesktopFormatter::getHeaderLabelFormatString() const { - char * fmt; - const auto mode = g_settings_get_enum(s, SETTINGS_TIME_FORMAT_S); + std::string fmt; + const auto mode = m_settings->time_format_mode.get(); if (mode == TIME_FORMAT_MODE_CUSTOM) { - fmt = g_settings_get_string(s, SETTINGS_CUSTOM_TIME_FORMAT_S); + fmt = m_settings->custom_time_format.get(); } else { - const auto show_day = g_settings_get_boolean(s, SETTINGS_SHOW_DAY_S); - const auto show_date = g_settings_get_boolean(s, SETTINGS_SHOW_DATE_S); - const auto show_year = show_date && g_settings_get_boolean(s, SETTINGS_SHOW_YEAR_S); + const auto show_day = m_settings->show_day.get(); + const auto show_date = m_settings->show_date.get(); + const auto show_year = show_date && m_settings->show_year.get(); const auto date_fmt = getDateFormat(show_day, show_date, show_year); - const auto time_fmt = getFullTimeFormatString(s); + const auto time_fmt = getFullTimeFormatString(); fmt = joinDateAndTimeFormatStrings(date_fmt, time_fmt); } return fmt; } -const gchar* T_(const gchar* in) const +const gchar* DesktopFormatter::getFullTimeFormatString() const { - return m_owner->T_(in); + const auto show_seconds = m_settings->show_seconds.get(); + + bool twelvehour; + switch (m_settings->time_format_mode.get()) + { + case TIME_FORMAT_MODE_LOCALE_DEFAULT: + twelvehour = is_locale_12h(); + break; + + case TIME_FORMAT_MODE_24_HOUR: + twelvehour = false; + break; + + default: + twelvehour = true; + break; + } + + return getDefaultHeaderTimeFormat(twelvehour, show_seconds); } -const gchar* getDateFormat(bool show_day, bool show_date, bool show_year) const +const gchar* DesktopFormatter::getDateFormat(bool show_day, bool show_date, bool show_year) const { const char * fmt; @@ -135,74 +159,6 @@ const gchar* getDateFormat(bool show_day, bool show_date, bool show_year) const return fmt; } -const gchar* getFullTimeFormatString(GSettings* settings) const -{ - auto show_seconds = g_settings_get_boolean(settings, SETTINGS_SHOW_SECONDS_S); - - bool twelvehour; - switch (g_settings_get_enum(settings, SETTINGS_TIME_FORMAT_S)) - { - case TIME_FORMAT_MODE_LOCALE_DEFAULT: - twelvehour = is_locale_12h(); - break; - - case TIME_FORMAT_MODE_24_HOUR: - twelvehour = false; - break; - - default: - twelvehour = true; - break; - } - - return m_owner->getDefaultHeaderTimeFormat(twelvehour, show_seconds); -} - -gchar* joinDateAndTimeFormatStrings(const char* date_string, - const char* time_string) const -{ - gchar * str; - - if (date_string && time_string) - { - /* TRANSLATORS: This is a format string passed to strftime to - * combine the date and the time. The value of "%s\u2003%s" - * will result in a string like this in US English 12-hour time: - * 'Fri Jul 16 11:50 AM'. The space in between date and time is - * a Unicode en space (E28082 in UTF-8 hex). */ - str = g_strdup_printf("%s\u2003%s", date_string, time_string); - } - else if (date_string) - { - str = g_strdup(date_string); - } - else // time_string - { - str = g_strdup(time_string); - } - - return str; -} - -private: - -DesktopFormatter * const m_owner; -std::shared_ptr m_clock; -GSettings * m_settings; -}; - -/*** -**** -***/ - -DesktopFormatter::DesktopFormatter(const std::shared_ptr& clock): - Formatter(clock), - p(new Impl(this, clock)) -{ -} - -DesktopFormatter::~DesktopFormatter() = default; - /*** **** ***/ diff --git a/src/formatter.cpp b/src/formatter.cpp index 1f26cc7..88a64df 100644 --- a/src/formatter.cpp +++ b/src/formatter.cpp @@ -124,7 +124,7 @@ guint calculate_seconds_until_next_fifteen_minutes(GDateTime * now) g_date_time_unref(next); return seconds; } -} // anonymous namespace +} // unnamed namespace @@ -167,7 +167,7 @@ private: { clearTimer(m_header_timer); - const std::string fmt = m_owner->headerFormat.get(); + const auto fmt = m_owner->headerFormat.get(); const bool header_shows_seconds = (fmt.find("%s") != std::string::npos) || (fmt.find("%S") != std::string::npos) || (fmt.find("%T") != std::string::npos) @@ -214,7 +214,7 @@ private: } private: - Formatter * const m_owner; + Formatter* const m_owner; guint m_header_timer = 0; guint m_relative_timer = 0; @@ -248,7 +248,7 @@ Formatter::is_locale_12h() return true; } -const char * +const char* Formatter::T_(const char *msg) { /* General strategy here is to make sure LANGUAGE is empty (since that @@ -264,17 +264,16 @@ Formatter::T_(const char *msg) LC_MESSAGES directory, so we won't find any translation there. */ - char *message_locale = g_strdup(setlocale(LC_MESSAGES, nullptr)); - const char *time_locale = setlocale(LC_TIME, nullptr); - char *language = g_strdup(g_getenv("LANGUAGE")); - const char *rv; + auto message_locale = g_strdup(setlocale(LC_MESSAGES, nullptr)); + const auto time_locale = setlocale(LC_TIME, nullptr); + auto language = g_strdup(g_getenv("LANGUAGE")); if (language) g_unsetenv("LANGUAGE"); setlocale(LC_MESSAGES, time_locale); /* Get the LC_TIME version */ - rv = _(msg); + const auto rv = _(msg); /* Put everything back the way it was */ setlocale(LC_MESSAGES, message_locale); @@ -286,10 +285,10 @@ Formatter::T_(const char *msg) return rv; } -const char * +const char* Formatter::getDefaultHeaderTimeFormat(bool twelvehour, bool show_seconds) { - const char * fmt; + const char* fmt; if (twelvehour && show_seconds) /* TRANSLATORS: a strftime(3) format for 12hr time w/seconds */ @@ -322,9 +321,9 @@ typedef enum } date_proximity_t; -date_proximity_t getDateProximity(GDateTime * now, GDateTime * time) +date_proximity_t getDateProximity(GDateTime* now, GDateTime* time) { - date_proximity_t prox = DATE_PROXIMITY_FAR; + auto prox = DATE_PROXIMITY_FAR; gint now_year, now_month, now_day; gint time_year, time_month, time_day; @@ -337,10 +336,9 @@ date_proximity_t getDateProximity(GDateTime * now, GDateTime * time) // does it happen tomorrow? if (prox == DATE_PROXIMITY_FAR) { - GDateTime * tomorrow; - gint tom_year, tom_month, tom_day; + auto tomorrow = g_date_time_add_days(now, 1); - tomorrow = g_date_time_add_days(now, 1); + gint tom_year, tom_month, tom_day; g_date_time_get_ymd(tomorrow, &tom_year, &tom_month, &tom_day); if ((tom_year == time_year) && (tom_month == time_month) && (tom_day == time_day)) prox = DATE_PROXIMITY_TOMORROW; @@ -351,14 +349,11 @@ date_proximity_t getDateProximity(GDateTime * now, GDateTime * time) // does it happen this week? if (prox == DATE_PROXIMITY_FAR) { - GDateTime * week; - GDateTime * week_bound; - - week = g_date_time_add_days(now, 6); - week_bound = g_date_time_new_local(g_date_time_get_year(week), - g_date_time_get_month(week), - g_date_time_get_day_of_month(week), - 23, 59, 59.9); + auto week = g_date_time_add_days(now, 6); + auto week_bound = g_date_time_new_local(g_date_time_get_year(week), + g_date_time_get_month(week), + g_date_time_get_day_of_month(week), + 23, 59, 59.9); if (g_date_time_compare(time, week_bound) <= 0) prox = DATE_PROXIMITY_WEEK; @@ -369,7 +364,7 @@ date_proximity_t getDateProximity(GDateTime * now, GDateTime * time) return prox; } -} // anonymous namespace +} // unnamed namespace /** * _ a time today should be shown as just the time (e.g. “3:55 PM”) @@ -391,7 +386,7 @@ std::string Formatter::getRelativeFormat(GDateTime* then, GDateTime* then_end) const { std::string ret; - auto now = p->m_clock->localtime().get(); + const auto now = p->m_clock->localtime().get(); if (then != nullptr) { @@ -448,7 +443,5 @@ Formatter::getRelativeFormat(GDateTime* then, GDateTime* then_end) const ***/ } // namespace datetime - } // namespace indicator - } // namespace unity diff --git a/tests/test-formatter.cc b/tests/test-formatter.cc index 42c828c..9950453 100644 --- a/tests/test-formatter.cc +++ b/tests/test-formatter.cc @@ -22,18 +22,14 @@ #include #include -#include +#include #include #include #include -using unity::indicator::datetime::Clock; -using unity::indicator::datetime::DateTime; -using unity::indicator::datetime::DesktopFormatter; -using unity::indicator::datetime::MockClock; -using unity::indicator::datetime::PhoneFormatter; +using namespace unity::indicator::datetime; /*** **** @@ -44,75 +40,73 @@ class FormatterFixture: public GlibFixture private: typedef GlibFixture super; - gchar * original_locale = nullptr; + gchar* m_original_locale = nullptr; protected: - GSettings * settings = nullptr; + std::shared_ptr m_settings; - virtual void SetUp () + virtual void SetUp() { - super::SetUp (); + super::SetUp(); - settings = g_settings_new (SETTINGS_INTERFACE); - - original_locale = g_strdup (setlocale (LC_TIME, NULL)); + m_settings.reset(new Settings); + m_original_locale = g_strdup(setlocale(LC_TIME, nullptr)); } - virtual void TearDown () + virtual void TearDown() { - g_clear_object (&settings); + m_settings.reset(); - setlocale (LC_TIME, original_locale); - g_clear_pointer (&original_locale, g_free); + setlocale(LC_TIME, m_original_locale); + g_clear_pointer(&m_original_locale, g_free); - super::TearDown (); + super::TearDown(); } - bool SetLocale (const char * expected_locale, const char * name) + bool SetLocale(const char* expected_locale, const char* name) { - setlocale (LC_TIME, expected_locale); - const char * actual_locale = setlocale (LC_TIME, NULL); - if (!g_strcmp0 (expected_locale, actual_locale)) + setlocale(LC_TIME, expected_locale); + const auto actual_locale = setlocale(LC_TIME, nullptr); + if (!g_strcmp0(expected_locale, actual_locale)) { return true; } else { - g_warning ("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); + g_warning("Unable to set locale to %s; skipping %s locale tests.", expected_locale, name); return false; } } - inline bool Set24hLocale () { return SetLocale ("C", "24h"); } - inline bool Set12hLocale () { return SetLocale ("en_US.utf8", "12h"); } + inline bool Set24hLocale() { return SetLocale("C", "24h"); } + inline bool Set12hLocale() { return SetLocale("en_US.utf8", "12h"); } }; /** * Test the phone header format */ -TEST_F (FormatterFixture, TestPhoneHeader) +TEST_F(FormatterFixture, TestPhoneHeader) { - GDateTime * now = g_date_time_new_local (2020, 10, 31, 18, 30, 59); - std::shared_ptr mock (new MockClock(DateTime(now))); + auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr clock(new MockClock(DateTime(now))); g_date_time_unref(now); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); // test the default value in a 24h locale - if (Set24hLocale ()) + if(Set24hLocale()) { - PhoneFormatter formatter (clock); - EXPECT_EQ (std::string("%H:%M"), formatter.headerFormat.get()); - EXPECT_EQ (std::string("18:30"), formatter.header.get()); + PhoneFormatter formatter(clock); + EXPECT_EQ(std::string("%H:%M"), formatter.headerFormat.get()); + EXPECT_EQ(std::string("18:30"), formatter.header.get()); } // test the default value in a 12h locale - if (Set12hLocale ()) + if(Set12hLocale()) { - PhoneFormatter formatter (clock); - EXPECT_EQ (std::string("%l:%M %p"), formatter.headerFormat.get()); - EXPECT_EQ (std::string(" 6:30 PM"), formatter.header.get()); + PhoneFormatter formatter(clock); + EXPECT_EQ(std::string("%l:%M %p"), formatter.headerFormat.get()); + EXPECT_EQ(std::string(" 6:30 PM"), formatter.header.get()); } } @@ -121,14 +115,14 @@ TEST_F (FormatterFixture, TestPhoneHeader) /** * Test the default values of the desktop header format */ -TEST_F (FormatterFixture, TestDesktopHeader) +TEST_F(FormatterFixture, TestDesktopHeader) { struct { bool is_12h; bool show_day; bool show_date; bool show_year; - const char * expected_format_string; + const char* expected_format_string; } test_cases[] = { { false, false, false, false, "%H:%M" }, { false, false, false, true, "%H:%M" }, // show_year is ignored iff show_date is false @@ -148,26 +142,21 @@ TEST_F (FormatterFixture, TestDesktopHeader) { true, true, true, true, "%a %b %e %Y" EM_SPACE "%l:%M %p" } }; - GDateTime * now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); - std::shared_ptr mock(new MockClock(DateTime(now))); + auto now = g_date_time_new_local(2020, 10, 31, 18, 30, 59); + std::shared_ptr clock(new MockClock(DateTime(now))); g_date_time_unref(now); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); - for (int i=0, n=G_N_ELEMENTS(test_cases); ishow_day.set(test_case.show_day); + m_settings->show_date.set(test_case.show_date); + m_settings->show_year.set(test_case.show_year); - ASSERT_STREQ (test_cases[i].expected_format_string, f.headerFormat.get().c_str()); - - g_settings_reset (settings, SETTINGS_SHOW_DAY_S); - g_settings_reset (settings, SETTINGS_SHOW_DATE_S); - g_settings_reset (settings, SETTINGS_SHOW_YEAR_S); + ASSERT_STREQ(test_case.expected_format_string, f.headerFormat.get().c_str()); } } } @@ -175,15 +164,15 @@ TEST_F (FormatterFixture, TestDesktopHeader) /** * Test the default values of the desktop header format */ -TEST_F (FormatterFixture, TestUpcomingTimes) +TEST_F(FormatterFixture, TestUpcomingTimes) { - auto a = g_date_time_new_local (2020, 10, 31, 18, 30, 59); + auto a = g_date_time_new_local(2020, 10, 31, 18, 30, 59); struct { gboolean is_12h; - GDateTime * now; - GDateTime * then; - const char * expected_format_string; + GDateTime* now; + GDateTime* then; + const char* expected_format_string; } test_cases[] = { { true, g_date_time_ref(a), g_date_time_ref(a), "%l:%M %p" }, // identical time { true, g_date_time_ref(a), g_date_time_add_hours(a,1), "%l:%M %p" }, // later today @@ -200,45 +189,42 @@ TEST_F (FormatterFixture, TestUpcomingTimes) { false, g_date_time_ref(a), g_date_time_add_days(a,7), "%a %d %b" EM_SPACE "%H:%M" } // over one week away }; - for (int i=0, n=G_N_ELEMENTS(test_cases); i mock (new MockClock(tmp));//DateTime(test_cases[i].now))); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); - DesktopFormatter f (clock); + std::shared_ptr clock (new MockClock(DateTime(test_case.now))); + DesktopFormatter f(clock, m_settings); - std::string fmt = f.getRelativeFormat (test_cases[i].then); - ASSERT_STREQ (test_cases[i].expected_format_string, fmt.c_str()); + const auto fmt = f.getRelativeFormat(test_case.then); + ASSERT_EQ(test_case.expected_format_string, fmt); - g_clear_pointer (&test_cases[i].now, g_date_time_unref); - g_clear_pointer (&test_cases[i].then, g_date_time_unref); + g_clear_pointer(&test_case.now, g_date_time_unref); + g_clear_pointer(&test_case.then, g_date_time_unref); } } - g_date_time_unref (a); + g_date_time_unref(a); } /** * Test the default values of the desktop header format */ -TEST_F (FormatterFixture, TestEventTimes) +TEST_F(FormatterFixture, TestEventTimes) { - auto day = g_date_time_new_local (2013, 1, 1, 13, 0, 0); - auto day_begin = g_date_time_new_local (2013, 1, 1, 13, 0, 0); - auto day_end = g_date_time_add_days (day_begin, 1); - auto tomorrow_begin = g_date_time_add_days (day_begin, 1); - auto tomorrow_end = g_date_time_add_days (tomorrow_begin, 1); + auto day = g_date_time_new_local(2013, 1, 1, 13, 0, 0); + auto day_begin = g_date_time_new_local(2013, 1, 1, 13, 0, 0); + auto day_end = g_date_time_add_days(day_begin, 1); + auto tomorrow_begin = g_date_time_add_days(day_begin, 1); + auto tomorrow_end = g_date_time_add_days(tomorrow_begin, 1); struct { bool is_12h; - GDateTime * now; - GDateTime * then; - GDateTime * then_end; - const char * expected_format_string; + GDateTime* now; + GDateTime* then; + GDateTime* then_end; + const char* expected_format_string; } test_cases[] = { { false, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, { true, g_date_time_ref(day), g_date_time_ref(day_begin), g_date_time_ref(day_end), _("Today") }, @@ -246,28 +232,25 @@ TEST_F (FormatterFixture, TestEventTimes) { true, g_date_time_ref(day), g_date_time_ref(tomorrow_begin), g_date_time_ref(tomorrow_end), _("Tomorrow") } }; - for (int i=0, n=G_N_ELEMENTS(test_cases); i mock (new MockClock(DateTime(test_cases[i].now))); - std::shared_ptr clock = std::dynamic_pointer_cast(mock); - DesktopFormatter f (clock); + std::shared_ptr clock(new MockClock(DateTime(test_case.now))); + DesktopFormatter f(clock, m_settings); - std::string fmt = f.getRelativeFormat (test_cases[i].then, test_cases[i].then_end); - ASSERT_STREQ (test_cases[i].expected_format_string, fmt.c_str()); + const auto fmt = f.getRelativeFormat(test_case.then, test_case.then_end); + ASSERT_STREQ(test_case.expected_format_string, fmt.c_str()); - g_clear_pointer (&test_cases[i].now, g_date_time_unref); - g_clear_pointer (&test_cases[i].then, g_date_time_unref); - g_clear_pointer (&test_cases[i].then_end, g_date_time_unref); + g_clear_pointer(&test_case.now, g_date_time_unref); + g_clear_pointer(&test_case.then, g_date_time_unref); + g_clear_pointer(&test_case.then_end, g_date_time_unref); } } - g_date_time_unref (tomorrow_end); - g_date_time_unref (tomorrow_begin); - g_date_time_unref (day_end); - g_date_time_unref (day_begin); - g_date_time_unref (day); + g_date_time_unref(tomorrow_end); + g_date_time_unref(tomorrow_begin); + g_date_time_unref(day_end); + g_date_time_unref(day_begin); + g_date_time_unref(day); } - - -- cgit v1.2.3