From 894c0c625ff1e2f2d031f48f157a3008302cb5a7 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 4 Feb 2014 00:10:17 -0600 Subject: pin the planner's upcoming appointments to the live clock time, rather than the calendar's time, so that they always update correctly in real-time --- include/datetime/planner-eds.h | 5 +- src/main.cpp | 2 +- src/planner-eds.cpp | 117 ++++++++++++++++++++++++----------------- tests/test-planner.cpp | 14 ++--- 4 files changed, 82 insertions(+), 56 deletions(-) diff --git a/include/datetime/planner-eds.h b/include/datetime/planner-eds.h index f3abce0..a99f611 100644 --- a/include/datetime/planner-eds.h +++ b/include/datetime/planner-eds.h @@ -20,9 +20,10 @@ #ifndef INDICATOR_DATETIME_PLANNER_EDS_H #define INDICATOR_DATETIME_PLANNER_EDS_H +#include #include -#include // unique_ptr +#include // shared_ptr, unique_ptr namespace unity { namespace indicator { @@ -34,7 +35,7 @@ namespace datetime { class PlannerEds: public Planner { public: - PlannerEds(); + PlannerEds(const std::shared_ptr& clock); virtual ~PlannerEds(); private: diff --git a/src/main.cpp b/src/main.cpp index 3c17923..87bfed1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,7 +64,7 @@ main(int /*argc*/, char** /*argv*/) state->settings = live_settings; state->clock = live_clock; state->locations.reset(new SettingsLocations(live_settings, live_timezones)); - state->planner.reset(new PlannerEds); + state->planner.reset(new PlannerEds(live_clock)); state->planner->time = live_clock->localtime(); std::shared_ptr actions(new LiveActions(state)); MenuFactory factory(actions, state); diff --git a/src/planner-eds.cpp b/src/planner-eds.cpp index 9048f52..7d9416c 100644 --- a/src/planner-eds.cpp +++ b/src/planner-eds.cpp @@ -41,18 +41,24 @@ class PlannerEds::Impl { public: - Impl(PlannerEds& owner): + Impl(PlannerEds& owner, const std::shared_ptr& clock): m_owner(owner), + m_clock(clock), m_cancellable(g_cancellable_new()) { e_source_registry_new(m_cancellable, on_source_registry_ready, this); + m_clock->minute_changed.connect([this](){ + g_debug("rebuilding upcoming because the clock's minute_changed"); + rebuild_soon(UPCOMING); + }); + m_owner.time.changed().connect([this](const DateTime& dt) { g_debug("planner's datetime property changed to %s; calling rebuild_soon()", dt.format("%F %T").c_str()); - rebuild_soon(); + rebuild_soon(MONTH); }); - rebuild_soon(); + rebuild_soon(ALL); } ~Impl() @@ -164,7 +170,7 @@ private: self); g_debug("client connected; calling rebuild_soon()"); - self->rebuild_soon(); + self->rebuild_soon(ALL); } } @@ -185,7 +191,7 @@ private: g_signal_connect(view, "objects-modified", G_CALLBACK(on_view_objects_modified), self); g_signal_connect(view, "objects-removed", G_CALLBACK(on_view_objects_removed), self); g_debug("view connected; calling rebuild_soon()"); - self->rebuild_soon(); + self->rebuild_soon(ALL); } else if(error != nullptr) { @@ -199,17 +205,17 @@ private: static void on_view_objects_added(ECalClientView* /*view*/, gpointer /*objects*/, gpointer gself) { g_debug("%s", G_STRFUNC); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } static void on_view_objects_modified(ECalClientView* /*view*/, gpointer /*objects*/, gpointer gself) { g_debug("%s", G_STRFUNC); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } static void on_view_objects_removed(ECalClientView* /*view*/, gpointer /*objects*/, gpointer gself) { g_debug("%s", G_STRFUNC); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } static void on_source_disabled(ESourceRegistry* /*registry*/, ESource* source, gpointer gself) @@ -228,7 +234,7 @@ private: g_warn_if_fail(n_disconnected == 3); g_object_unref(view); m_views.erase(vit); - rebuild_soon(); + rebuild_soon(ALL); } // if an ECalClient is associated with this source, remove it @@ -238,7 +244,7 @@ private: auto& client = cit->second; g_object_unref(client); m_clients.erase(cit); - rebuild_soon(); + rebuild_soon(ALL); } } @@ -255,14 +261,14 @@ private: { g_object_unref(*sit); m_sources.erase(sit); - rebuild_soon(); + rebuild_soon(ALL); } } static void on_source_changed(ESourceRegistry* /*registry*/, ESource* /*source*/, gpointer gself) { g_debug("source changed; calling rebuild_soon()"); - static_cast(gself)->rebuild_soon(); + static_cast(gself)->rebuild_soon(ALL); } private: @@ -286,9 +292,11 @@ private: task(task_in), client(client_in), color(color_in) {} }; - void rebuild_soon() + void rebuild_soon(int rebuild_flags) { - const static guint ARBITRARY_INTERVAL_SECS = 2; + static const guint ARBITRARY_INTERVAL_SECS = 2; + + m_rebuild_flags |= rebuild_flags; if (m_rebuild_tag == 0) m_rebuild_tag = g_timeout_add_seconds(ARBITRARY_INTERVAL_SECS, rebuild_now_static, this); @@ -297,44 +305,56 @@ private: static gboolean rebuild_now_static(gpointer gself) { auto self = static_cast(gself); + const auto flags = self->m_rebuild_flags; self->m_rebuild_tag = 0; - self->rebuild_now(); + self->m_rebuild_flags = 0; + self->rebuild_now(flags); return G_SOURCE_REMOVE; } - void rebuild_now() + void rebuild_now(int rebuild_flags) { - const auto calendar_date = m_owner.time.get().get(); - GDateTime* begin; - GDateTime* end; - int y, m, d; - - // get all the appointments in the calendar month - g_date_time_get_ymd(calendar_date, &y, &m, &d); - begin = g_date_time_new_local(y, m, 1, 0, 0, 0.1); - end = g_date_time_new_local(y, m, g_date_get_days_in_month(GDateMonth(m),GDateYear(y)), 23, 59, 59.9); - if (begin && end) - { - get_appointments(begin, end, [this](const std::vector& appointments) { - g_debug("got %d appointments in this calendar month", (int)appointments.size()); - m_owner.this_month.set(appointments); - }); - } - g_clear_pointer(&begin, g_date_time_unref); - g_clear_pointer(&end, g_date_time_unref); + if (rebuild_flags & UPCOMING) + rebuild_upcoming(); - // get the upcoming appointments - begin = g_date_time_ref(calendar_date); - end = g_date_time_add_months(begin, 1); - if (begin && end) - { - get_appointments(begin, end, [this](const std::vector& appointments) { - g_debug("got %d upcoming appointments", (int)appointments.size()); - m_owner.upcoming.set(appointments); - }); - } - g_clear_pointer(&begin, g_date_time_unref); - g_clear_pointer(&end, g_date_time_unref); + if (rebuild_flags & MONTH) + rebuild_month(); + } + + void rebuild_month() + { + const auto ref = m_owner.time.get().get(); + auto month_begin = g_date_time_add_full(ref, + 0, // subtract no years + 0, // subtract no months + -(g_date_time_get_day_of_month(ref)-1), + -g_date_time_get_hour(ref), + -g_date_time_get_minute(ref), + -g_date_time_get_seconds(ref)); + auto month_end = g_date_time_add_full(month_begin, 0, 1, 0, 0, 0, -0.1); + + get_appointments(month_begin, month_end, [this](const std::vector& appointments) { + g_debug("got %d appointments in this calendar month", (int)appointments.size()); + m_owner.this_month.set(appointments); + }); + + g_date_time_unref(month_end); + g_date_time_unref(month_begin); + } + + void rebuild_upcoming() + { + const auto ref = m_clock->localtime(); + const auto begin = g_date_time_add_minutes(ref.get(),-10); + const auto end = g_date_time_add_months(begin,1); + + get_appointments(begin, end, [this](const std::vector& appointments) { + g_debug("got %d upcoming appointments", (int)appointments.size()); + m_owner.upcoming.set(appointments); + }); + + g_date_time_unref(end); + g_date_time_unref(begin); } void get_appointments(GDateTime* begin_dt, GDateTime* end_dt, appointment_func func) @@ -496,15 +516,18 @@ private: } PlannerEds& m_owner; + std::shared_ptr m_clock; std::set m_sources; std::map m_clients; std::map m_views; GCancellable* m_cancellable = nullptr; ESourceRegistry* m_source_registry = nullptr; guint m_rebuild_tag = 0; + guint m_rebuild_flags = 0; + enum { UPCOMING=(1<<0), MONTH=(1<<1), ALL=UPCOMING|MONTH }; }; -PlannerEds::PlannerEds(): p(new Impl(*this)) {} +PlannerEds::PlannerEds(const std::shared_ptr& clock): p(new Impl(*this, clock)) {} PlannerEds::~PlannerEds() =default; diff --git a/tests/test-planner.cpp b/tests/test-planner.cpp index b476ee8..1923ba1 100644 --- a/tests/test-planner.cpp +++ b/tests/test-planner.cpp @@ -28,9 +28,7 @@ #include #include -using unity::indicator::datetime::Appointment; -using unity::indicator::datetime::DateTime; -using unity::indicator::datetime::PlannerEds; +using namespace unity::indicator::datetime; /*** **** @@ -40,11 +38,15 @@ typedef GlibFixture PlannerFixture; TEST_F(PlannerFixture, EDS) { - PlannerEds planner; + auto tmp = g_date_time_new_now_local(); + const auto now = DateTime(tmp); + g_date_time_unref(tmp); + + std::shared_ptr clock(new MockClock(now)); + PlannerEds planner(clock); wait_msec(100); - auto now = g_date_time_new_now_local(); - planner.time.set(DateTime(now)); + planner.time.set(now); wait_msec(2500); std::vector this_month = planner.this_month.get(); -- cgit v1.2.3