diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/clock-live.cpp | 31 | ||||
-rw-r--r-- | src/main.cpp | 14 | ||||
-rw-r--r-- | src/planner-range.cpp | 7 | ||||
-rw-r--r-- | src/timezone-file.cpp | 175 | ||||
-rw-r--r-- | src/timezone-geoclue.cpp | 391 | ||||
-rw-r--r-- | src/wakeup-timer-powerd.cpp | 2 |
6 files changed, 351 insertions, 269 deletions
diff --git a/src/clock-live.cpp b/src/clock-live.cpp index 21a18a3..68a8a8b 100644 --- a/src/clock-live.cpp +++ b/src/clock-live.cpp @@ -18,7 +18,7 @@ */ #include <datetime/clock.h> -#include <datetime/timezones.h> +#include <datetime/timezone.h> namespace unity { namespace indicator { @@ -59,14 +59,15 @@ class LiveClock::Impl { public: - Impl(LiveClock& owner, const std::shared_ptr<const Timezones>& tzd): + Impl(LiveClock& owner, const std::shared_ptr<const Timezone>& timezone_): m_owner(owner), - m_timezones(tzd) + m_timezone(timezone_) { - if (m_timezones) + if (m_timezone) { - m_timezones->timezone.changed().connect([this](const std::string& z) {setTimezone(z);}); - setTimezone(m_timezones->timezone.get()); + auto setter = [this](const std::string& z){setTimezone(z);}; + m_timezone->timezone.changed().connect(setter); + setter(m_timezone->timezone.get()); } restart_minute_timer(); @@ -76,14 +77,14 @@ public: { clearTimer(m_timer); - g_clear_pointer(&m_timezone, g_time_zone_unref); + g_clear_pointer(&m_gtimezone, g_time_zone_unref); } DateTime localtime() const { - g_assert(m_timezone != nullptr); + g_assert(m_gtimezone != nullptr); - auto gdt = g_date_time_new_now(m_timezone); + auto gdt = g_date_time_new_now(m_gtimezone); DateTime ret(gdt); g_date_time_unref(gdt); return ret; @@ -93,8 +94,8 @@ private: void setTimezone(const std::string& str) { - g_clear_pointer(&m_timezone, g_time_zone_unref); - m_timezone = g_time_zone_new(str.c_str()); + g_clear_pointer(&m_gtimezone, g_time_zone_unref); + m_gtimezone = g_time_zone_new(str.c_str()); m_owner.minute_changed(); } @@ -134,15 +135,15 @@ private: protected: LiveClock& m_owner; - GTimeZone* m_timezone = nullptr; - std::shared_ptr<const Timezones> m_timezones; + GTimeZone* m_gtimezone = nullptr; + std::shared_ptr<const Timezone> m_timezone; DateTime m_prev_datetime; unsigned int m_timer = 0; }; -LiveClock::LiveClock(const std::shared_ptr<const Timezones>& tzd): - p(new Impl(*this, tzd)) +LiveClock::LiveClock(const std::shared_ptr<const Timezone>& timezone_): + p(new Impl(*this, timezone_)) { } diff --git a/src/main.cpp b/src/main.cpp index 54517c9..aa8f829 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,20 +63,20 @@ namespace } std::shared_ptr<State> create_state(const std::shared_ptr<Engine>& engine, - const std::shared_ptr<Timezone>& tz) + const std::shared_ptr<Timezone>& timezone_) { // create the live objects auto live_settings = std::make_shared<LiveSettings>(); auto live_timezones = std::make_shared<LiveTimezones>(live_settings, TIMEZONE_FILE); - auto live_clock = std::make_shared<LiveClock>(live_timezones); + auto live_clock = std::make_shared<LiveClock>(timezone_); // create a full-month planner currently pointing to the current month const auto now = live_clock->localtime(); - auto range_planner = std::make_shared<SimpleRangePlanner>(engine, tz); + auto range_planner = std::make_shared<SimpleRangePlanner>(engine, timezone_); auto calendar_month = std::make_shared<MonthPlanner>(range_planner, now); // create an upcoming-events planner currently pointing to the current date - range_planner = std::make_shared<SimpleRangePlanner>(engine, tz); + range_planner = std::make_shared<SimpleRangePlanner>(engine, timezone_); auto calendar_upcoming = std::make_shared<UpcomingPlanner>(range_planner, now); // create the state @@ -127,8 +127,8 @@ main(int /*argc*/, char** /*argv*/) textdomain(GETTEXT_PACKAGE); auto engine = create_engine(); - auto timezone = std::make_shared<FileTimezone>(TIMEZONE_FILE); - auto state = create_state(engine, timezone); + auto timezone_ = std::make_shared<FileTimezone>(TIMEZONE_FILE); + auto state = create_state(engine, timezone_); auto actions = std::make_shared<LiveActions>(state); MenuFactory factory(actions, state); @@ -136,7 +136,7 @@ main(int /*argc*/, char** /*argv*/) auto snooze_planner = std::make_shared<SnoozePlanner>(state->settings, state->clock); auto notification_engine = std::make_shared<uin::Engine>("indicator-datetime-service"); std::unique_ptr<Snap> snap (new Snap(notification_engine, state->settings)); - auto alarm_queue = create_simple_alarm_queue(state->clock, snooze_planner, engine, timezone); + auto alarm_queue = create_simple_alarm_queue(state->clock, snooze_planner, engine, timezone_); auto on_snooze = [snooze_planner](const Appointment& a) {snooze_planner->add(a);}; auto on_ok = [](const Appointment&){}; auto on_alarm_reached = [&snap, &on_snooze, &on_ok](const Appointment& a) {(*snap)(a, on_snooze, on_ok);}; diff --git a/src/planner-range.cpp b/src/planner-range.cpp index 41b0f56..c223665 100644 --- a/src/planner-range.cpp +++ b/src/planner-range.cpp @@ -28,7 +28,7 @@ namespace datetime { ***/ SimpleRangePlanner::SimpleRangePlanner(const std::shared_ptr<Engine>& engine, - const std::shared_ptr<Timezone>& timezone): + const std::shared_ptr<Timezone>& timezone): m_engine(engine), m_timezone(timezone), m_range(std::pair<DateTime,DateTime>(DateTime::NowLocal(), DateTime::NowLocal())) @@ -38,6 +38,11 @@ SimpleRangePlanner::SimpleRangePlanner(const std::shared_ptr<Engine>& engine, rebuild_soon(); }); + m_timezone->timezone.changed().connect([this](const std::string& s){ + g_debug("RangePlanner %p rebuilding soon because the timezone changed to '%s'", this, s.c_str()); + rebuild_soon(); + }); + range().changed().connect([this](const std::pair<DateTime,DateTime>&){ g_debug("rebuilding because the date range changed"); rebuild_soon(); diff --git a/src/timezone-file.cpp b/src/timezone-file.cpp index bbe48f7..3c73913 100644 --- a/src/timezone-file.cpp +++ b/src/timezone-file.cpp @@ -19,11 +19,97 @@ #include <datetime/timezone-file.h> +#include <gio/gio.h> + #include <cerrno> #include <cstdlib> -namespace +namespace unity { +namespace indicator { +namespace datetime { + +/*** +**** +***/ + +class FileTimezone::Impl { +public: + + Impl(FileTimezone& owner, const std::string& filename): + m_owner(owner) + { + set_filename(filename); + } + + ~Impl() + { + clear(); + } + +private: + + void clear() + { + if (m_monitor_handler_id) + g_signal_handler_disconnect(m_monitor, m_monitor_handler_id); + + g_clear_object (&m_monitor); + + m_filename.clear(); + } + + void set_filename(const std::string& filename) + { + clear(); + + auto tmp = realpath(filename.c_str(), nullptr); + if(tmp != nullptr) + { + m_filename = tmp; + free(tmp); + } + else + { + g_warning("Unable to resolve path '%s': %s", filename.c_str(), g_strerror(errno)); + m_filename = filename; // better than nothing? + } + + auto file = g_file_new_for_path(m_filename.c_str()); + GError * err = nullptr; + m_monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, nullptr, &err); + g_object_unref(file); + if (err) + { + g_warning("%s Unable to monitor timezone file '%s': %s", G_STRLOC, TIMEZONE_FILE, err->message); + g_error_free(err); + } + else + { + m_monitor_handler_id = g_signal_connect_swapped(m_monitor, "changed", G_CALLBACK(on_file_changed), this); + g_debug("%s Monitoring timezone file '%s'", G_STRLOC, m_filename.c_str()); + } + + reload(); + } + + static void on_file_changed(gpointer gself) + { + static_cast<Impl*>(gself)->reload(); + } + + void reload() + { + const auto new_timezone = get_timezone_from_file(m_filename); + + if (!new_timezone.empty()) + m_owner.timezone.set(new_timezone); + } + + /*** + **** + ***/ + std::string get_timezone_from_file(const std::string& filename) { GError * error; @@ -73,86 +159,33 @@ namespace return ret; } -} -namespace unity { -namespace indicator { -namespace datetime { + /*** + **** + ***/ -FileTimezone::FileTimezone() -{ -} + FileTimezone & m_owner; + std::string m_filename; + GFileMonitor * m_monitor = nullptr; + unsigned long m_monitor_handler_id = 0; +}; -FileTimezone::FileTimezone(const std::string& filename) -{ - set_filename(filename); -} - -FileTimezone::~FileTimezone() -{ - clear(); -} +/*** +**** +***/ -void -FileTimezone::clear() +FileTimezone::FileTimezone(const std::string& filename): + impl(new Impl{*this, filename}) { - if (m_monitor_handler_id) - g_signal_handler_disconnect(m_monitor, m_monitor_handler_id); - - g_clear_object (&m_monitor); - - m_filename.clear(); } -void -FileTimezone::set_filename(const std::string& filename) -{ - clear(); - - auto tmp = realpath(filename.c_str(), nullptr); - if(tmp != nullptr) - { - m_filename = tmp; - free(tmp); - } - else - { - g_warning("Unable to resolve path '%s': %s", filename.c_str(), g_strerror(errno)); - m_filename = filename; // better than nothing? - } - - auto file = g_file_new_for_path(m_filename.c_str()); - GError * err = nullptr; - m_monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, nullptr, &err); - g_object_unref(file); - if (err) - { - g_warning("%s Unable to monitor timezone file '%s': %s", G_STRLOC, TIMEZONE_FILE, err->message); - g_error_free(err); - } - else - { - m_monitor_handler_id = g_signal_connect_swapped(m_monitor, "changed", G_CALLBACK(on_file_changed), this); - g_debug("%s Monitoring timezone file '%s'", G_STRLOC, m_filename.c_str()); - } - - reload(); -} - -void -FileTimezone::on_file_changed(gpointer gself) +FileTimezone::~FileTimezone() { - static_cast<FileTimezone*>(gself)->reload(); } -void -FileTimezone::reload() -{ - const auto new_timezone = get_timezone_from_file(m_filename); - - if (!new_timezone.empty()) - timezone.set(new_timezone); -} +/*** +**** +***/ } // namespace datetime } // namespace indicator diff --git a/src/timezone-geoclue.cpp b/src/timezone-geoclue.cpp index b8847a4..ca9132f 100644 --- a/src/timezone-geoclue.cpp +++ b/src/timezone-geoclue.cpp @@ -19,225 +19,266 @@ #include <datetime/timezone-geoclue.h> +#include <gio/gio.h> + +#include <memory> +#include <string> +#include <vector> + #define GEOCLUE_BUS_NAME "org.freedesktop.Geoclue.Master" namespace unity { namespace indicator { namespace datetime { - -GeoclueTimezone::GeoclueTimezone(): - m_cancellable(g_cancellable_new()) -{ - g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_got, this); -} - -GeoclueTimezone::~GeoclueTimezone() +class GeoclueTimezone::Impl { - g_cancellable_cancel(m_cancellable); - g_object_unref(m_cancellable); - if (m_signal_subscription) - g_dbus_connection_signal_unsubscribe(m_connection, m_signal_subscription); +public: - g_object_unref(m_connection); -} - -/*** -**** -***/ - -void -GeoclueTimezone::on_bus_got(GObject* /*source*/, - GAsyncResult* res, - gpointer gself) -{ - GError * error; - GDBusConnection * connection; - - error = nullptr; - connection = g_bus_get_finish(res, &error); - if (error) + Impl(GeoclueTimezone& owner): + m_owner(owner), + m_cancellable(g_cancellable_new()) { - if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("Couldn't get bus: %s", error->message); - - g_error_free(error); + g_bus_get(G_BUS_TYPE_SESSION, m_cancellable, on_bus_got, this); } - else + + ~Impl() { - auto self = static_cast<GeoclueTimezone*>(gself); - - self->m_connection = connection; - - g_dbus_connection_call(self->m_connection, - GEOCLUE_BUS_NAME, - "/org/freedesktop/Geoclue/Master", - "org.freedesktop.Geoclue.Master", - "Create", - nullptr, // parameters - G_VARIANT_TYPE("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - self->m_cancellable, - on_client_created, - self); + g_cancellable_cancel(m_cancellable); + g_object_unref(m_cancellable); + g_object_unref(m_bus); } -} -void -GeoclueTimezone::on_client_created(GObject * source, GAsyncResult * res, gpointer gself) -{ - GVariant * result; +private: - if ((result = call_finish(source, res))) + void remember_subscription(GDBusConnection * bus, + guint tag) { - auto self = static_cast<GeoclueTimezone*>(gself); - - GVariant * child = g_variant_get_child_value(result, 0); - self->m_client_object_path = g_variant_get_string(child, nullptr); - g_variant_unref(child); - g_variant_unref(result); - - self->m_signal_subscription = g_dbus_connection_signal_subscribe( - self->m_connection, - GEOCLUE_BUS_NAME, - "org.freedesktop.Geoclue.Address", // inteface - "AddressChanged", // signal name - self->m_client_object_path.c_str(), // object path - nullptr, // arg0 - G_DBUS_SIGNAL_FLAGS_NONE, - on_address_changed, - self, - nullptr); - - g_dbus_connection_call(self->m_connection, - GEOCLUE_BUS_NAME, - self->m_client_object_path.c_str(), - "org.freedesktop.Geoclue.MasterClient", - "SetRequirements", - g_variant_new("(iibi)", 2, 0, FALSE, 1023), - nullptr, - G_DBUS_CALL_FLAGS_NONE, - -1, - self->m_cancellable, - on_requirements_set, - self); - } -} + g_object_ref(bus); -void -GeoclueTimezone::on_address_changed(GDBusConnection* /*connection*/, - const gchar* /*sender_name*/, - const gchar* /*object_path*/, - const gchar* /*interface_name*/, - const gchar* /*signal_name*/, - GVariant* parameters, - gpointer gself) -{ - static_cast<GeoclueTimezone*>(gself)->setTimezoneFromAddressVariant(parameters); -} + auto deleter = [tag](GDBusConnection* bus){ + g_dbus_connection_signal_unsubscribe(bus, tag); + g_object_unref(G_OBJECT(bus)); + }; -void -GeoclueTimezone::on_requirements_set(GObject* source, GAsyncResult* res, gpointer gself) -{ - GVariant * result; + m_subscriptions.push_back(std::shared_ptr<GDBusConnection>(bus, deleter)); + } - if ((result = call_finish(source, res))) + static void on_bus_got(GObject * /*source*/, + GAsyncResult * res, + gpointer gself) { - auto self = static_cast<GeoclueTimezone*>(gself); - - g_dbus_connection_call(self->m_connection, - GEOCLUE_BUS_NAME, - self->m_client_object_path.c_str(), - "org.freedesktop.Geoclue.MasterClient", - "AddressStart", - nullptr, - nullptr, - G_DBUS_CALL_FLAGS_NONE, - -1, - self->m_cancellable, - on_address_started, - self); - - g_variant_unref(result); - } -} + GError * error; + GDBusConnection * connection; -void -GeoclueTimezone::on_address_started(GObject * source, GAsyncResult * res, gpointer gself) -{ - GVariant * result; + error = nullptr; + connection = g_bus_get_finish(res, &error); + if (error) + { + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning("Couldn't get bus: %s", error->message); - if ((result = call_finish(source, res))) + g_error_free(error); + } + else + { + auto self = static_cast<Impl*>(gself); + + self->m_bus = connection; + + g_dbus_connection_call(self->m_bus, + GEOCLUE_BUS_NAME, + "/org/freedesktop/Geoclue/Master", + "org.freedesktop.Geoclue.Master", + "Create", + nullptr, // parameters + G_VARIANT_TYPE("(o)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + self->m_cancellable, + on_client_created, + self); + } + } + + static void on_client_created(GObject* source, GAsyncResult* res, gpointer gself) { - auto self = static_cast<GeoclueTimezone*>(gself); - - g_dbus_connection_call(self->m_connection, - GEOCLUE_BUS_NAME, - self->m_client_object_path.c_str(), - "org.freedesktop.Geoclue.Address", - "GetAddress", - nullptr, - G_VARIANT_TYPE("(ia{ss}(idd))"), - G_DBUS_CALL_FLAGS_NONE, - -1, - self->m_cancellable, - on_address_got, - self); - - g_variant_unref(result); + GVariant * result; + + if ((result = call_finish(G_STRFUNC, source, res))) + { + auto self = static_cast<Impl*>(gself); + + GVariant * child = g_variant_get_child_value(result, 0); + self->m_client_object_path = g_variant_get_string(child, nullptr); + g_variant_unref(child); + g_variant_unref(result); + + auto tag = g_dbus_connection_signal_subscribe(self->m_bus, + GEOCLUE_BUS_NAME, + "org.freedesktop.Geoclue.Address", // interface + "AddressChanged", // signal name + self->m_client_object_path.c_str(), // object path + nullptr, // arg0 + G_DBUS_SIGNAL_FLAGS_NONE, + on_address_changed, + self, + nullptr); + self->remember_subscription(self->m_bus, tag); + + g_dbus_connection_call(self->m_bus, + GEOCLUE_BUS_NAME, + self->m_client_object_path.c_str(), + "org.freedesktop.Geoclue.MasterClient", + "SetRequirements", + g_variant_new("(iibi)", 2, 0, FALSE, 1023), + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + self->m_cancellable, + on_requirements_set, + self); + } } -} -void -GeoclueTimezone::on_address_got(GObject * source, GAsyncResult * res, gpointer gself) -{ - GVariant * result; + static void on_address_changed(GDBusConnection* /*connection*/, + const gchar* /*sender_name*/, + const gchar* /*object_path*/, + const gchar* /*interface_name*/, + const gchar* /*signal_name*/, + GVariant* parameters, + gpointer gself) + { + static_cast<Impl*>(gself)->set_timezone_from_address_variant(parameters); + } - if ((result = call_finish(source, res))) + static void on_requirements_set(GObject* source, GAsyncResult* res, gpointer gself) { - static_cast<GeoclueTimezone*>(gself)->setTimezoneFromAddressVariant(result); - g_variant_unref(result); + GVariant * result; + + if ((result = call_finish(G_STRFUNC, source, res))) + { + auto self = static_cast<Impl*>(gself); + + g_dbus_connection_call(self->m_bus, + GEOCLUE_BUS_NAME, + self->m_client_object_path.c_str(), + "org.freedesktop.Geoclue.MasterClient", + "AddressStart", + nullptr, + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + self->m_cancellable, + on_address_started, + self); + + g_variant_unref(result); + } } -} -void -GeoclueTimezone::setTimezoneFromAddressVariant(GVariant * variant) -{ - g_return_if_fail(g_variant_is_of_type(variant, G_VARIANT_TYPE("(ia{ss}(idd))"))); + static void on_address_started(GObject* source, GAsyncResult* res, gpointer gself) + { + GVariant * result; + + if ((result = call_finish(G_STRFUNC, source, res))) + { + auto self = static_cast<Impl*>(gself); + + g_dbus_connection_call(self->m_bus, + GEOCLUE_BUS_NAME, + self->m_client_object_path.c_str(), + "org.freedesktop.Geoclue.Address", + "GetAddress", + nullptr, + G_VARIANT_TYPE("(ia{ss}(idd))"), + G_DBUS_CALL_FLAGS_NONE, + -1, + self->m_cancellable, + on_address_got, + self); + + g_variant_unref(result); + } + } - const gchar * timezone_string = nullptr; - GVariant * dict = g_variant_get_child_value(variant, 1); - if (dict) + static void on_address_got(GObject* source, GAsyncResult* res, gpointer gself) { - if (g_variant_lookup(dict, "timezone", "&s", &timezone_string)) - timezone.set(timezone_string); + GVariant * result; - g_variant_unref(dict); + if ((result = call_finish(G_STRFUNC, source, res))) + { + static_cast<Impl*>(gself)->set_timezone_from_address_variant(result); + g_variant_unref(result); + } } -} -GVariant* -GeoclueTimezone::call_finish(GObject * source, GAsyncResult * res) -{ - GError * error; - GVariant * result; + /*** + **** + ***/ - error = nullptr; - result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error); + void set_timezone_from_address_variant(GVariant * variant) + { + g_return_if_fail(g_variant_is_of_type(variant, G_VARIANT_TYPE("(ia{ss}(idd))"))); + + const gchar * timezone_string = nullptr; + GVariant * dict = g_variant_get_child_value(variant, 1); + if (dict) + { + if (g_variant_lookup(dict, "timezone", "&s", &timezone_string)) + { + g_debug("from geoclue, setting timezone to '%s'", timezone_string); + m_owner.timezone.set(timezone_string); + } + + g_variant_unref(dict); + } + } - if (error) + static GVariant* call_finish(const char * funcname, GObject * source, GAsyncResult * res) { + GError * error; + GVariant * result; + + error = nullptr; + result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error); + + if (error) + { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("AddressStart() failed: %s", error->message); + g_warning("%s failed: %s", funcname, error->message); g_error_free(error); g_clear_pointer(&result, g_variant_unref); + } + + return result; } - return result; + /*** + **** + ***/ + + GeoclueTimezone & m_owner; + GDBusConnection * m_bus = nullptr; + GCancellable * m_cancellable = nullptr; + std::string m_client_object_path; + std::vector<std::shared_ptr<GDBusConnection>> m_subscriptions; +}; + +/**** +***** +****/ + +GeoclueTimezone::GeoclueTimezone(): + impl(new Impl{*this}) +{ +} + +GeoclueTimezone::~GeoclueTimezone() +{ } /**** diff --git a/src/wakeup-timer-powerd.cpp b/src/wakeup-timer-powerd.cpp index 3c4b322..ab6859f 100644 --- a/src/wakeup-timer-powerd.cpp +++ b/src/wakeup-timer-powerd.cpp @@ -22,6 +22,8 @@ #include <notifications/dbus-shared.h> // BUS_POWERD_NAME +#include <gio/gio.h> + #include <memory> // std::shared_ptr namespace unity { |