From 060bc69d8bdfe9860a71109ecf92810beb99f4da Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 17 Dec 2013 21:59:43 -0600 Subject: add clock + tests --- src/clock-live.cpp | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/clock-live.cpp (limited to 'src/clock-live.cpp') diff --git a/src/clock-live.cpp b/src/clock-live.cpp new file mode 100644 index 0000000..80e91a3 --- /dev/null +++ b/src/clock-live.cpp @@ -0,0 +1,137 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +namespace unity { +namespace indicator { +namespace datetime { + +class LiveClock::Impl +{ +public: + + Impl(LiveClock& owner, const std::shared_ptr& tzd): + owner_(owner), + timezones_(tzd) + { + if (timezones_) + { + timezones_->timezone.changed().connect ([this](const std::string& z) {setTimezone(z);}); + setTimezone(timezones_->timezone.get()); + } + + owner_.skewTestIntervalSec.changed().connect([this](unsigned int intervalSec) {setInterval(intervalSec);}); + setInterval(owner_.skewTestIntervalSec.get()); + } + + ~Impl() + { + clearTimer(); + + g_clear_pointer (&timezone_, g_time_zone_unref); + } + + GDateTime* localtime() const + { + g_assert (timezone_ != nullptr); + + return g_date_time_new_now (timezone_); + } + +private: + + void setTimezone (const std::string& str) + { + g_clear_pointer (&timezone_, g_time_zone_unref); + timezone_= g_time_zone_new (str.c_str()); + owner_.skewDetected(); + } + +private: + + void clearTimer() + { + if (skew_timeout_id_) + { + g_source_remove(skew_timeout_id_); + skew_timeout_id_ = 0; + } + + g_clear_pointer(&prev_datetime_, g_date_time_unref); + } + + void setInterval(unsigned int seconds) + { + clearTimer(); + + if (seconds > 0) + { + prev_datetime_ = owner_.localtime(); + skew_timeout_id_ = g_timeout_add_seconds(seconds, onTimerPulse, this); + } + } + + static gboolean onTimerPulse(gpointer gself) + { + auto self = static_cast(gself); + + // check to see if too much time passed since the last check */ + GDateTime * now = self->owner_.localtime(); + const GTimeSpan diff = g_date_time_difference(now, self->prev_datetime_); + const GTimeSpan fuzz = 5; + const GTimeSpan max = (self->owner_.skewTestIntervalSec.get() + fuzz) * G_USEC_PER_SEC; + if (abs(diff) > max) + self->owner_.skewDetected(); + + // update prev_datetime + g_clear_pointer(&self->prev_datetime_, g_date_time_unref); + self->prev_datetime_ = now; + + return G_SOURCE_CONTINUE; + } + +protected: + + LiveClock& owner_; + GTimeZone * timezone_ = nullptr; + std::shared_ptr timezones_; + + GDateTime * prev_datetime_ = nullptr; + unsigned int skew_timeout_id_ = 0; + unsigned int sleep_subscription_id_ = 0; +}; + +LiveClock::LiveClock(const std::shared_ptr& tzd): + p (new Impl (*this, tzd)) +{ +} + +LiveClock::~LiveClock() =default; + +GDateTime * +LiveClock::localtime() const +{ + return p->localtime(); +} + +} // namespace datetime +} // namespace indicator +} // namespace unity + -- cgit v1.2.3