aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/main.cpp4
-rw-r--r--src/timezone-file.cpp199
-rw-r--r--src/timezones-live.cpp5
4 files changed, 113 insertions, 98 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5fc822c..6f27e99 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,8 +1,7 @@
set (SERVICE_LIB "indicatordatetimeservice")
set (SERVICE_EXEC "indicator-datetime-service")
-add_definitions (-DTIMEZONE_FILE="/etc/timezone"
- -DG_LOG_DOMAIN="Indicator-Datetime")
+add_definitions (-DG_LOG_DOMAIN="Indicator-Datetime")
# handwritten sources
set (SERVICE_C_SOURCES
diff --git a/src/main.cpp b/src/main.cpp
index 907d49f..460f98c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -68,7 +68,7 @@ namespace
{
// create the live objects
auto live_settings = std::make_shared<LiveSettings>();
- auto live_timezones = std::make_shared<LiveTimezones>(live_settings, TIMEZONE_FILE);
+ auto live_timezones = std::make_shared<LiveTimezones>(live_settings);
auto live_clock = std::make_shared<LiveClock>(timezone_);
// create a full-month planner currently pointing to the current month
@@ -128,7 +128,7 @@ main(int /*argc*/, char** /*argv*/)
textdomain(GETTEXT_PACKAGE);
auto engine = create_engine();
- auto timezone_ = std::make_shared<FileTimezone>(TIMEZONE_FILE);
+ auto timezone_ = std::make_shared<FileTimezone>();
auto state = create_state(engine, timezone_);
auto actions = std::make_shared<LiveActions>(state);
MenuFactory factory(actions, state);
diff --git a/src/timezone-file.cpp b/src/timezone-file.cpp
index 3c73913..15e4f61 100644
--- a/src/timezone-file.cpp
+++ b/src/timezone-file.cpp
@@ -36,10 +36,11 @@ class FileTimezone::Impl
{
public:
- Impl(FileTimezone& owner, const std::string& filename):
- m_owner(owner)
+ Impl(FileTimezone& owner):
+ m_owner(owner),
+ m_loop(g_main_loop_new(nullptr, FALSE))
{
- set_filename(filename);
+ monitor_timezone_property();
}
~Impl()
@@ -51,113 +52,128 @@ 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)
+ if (m_bus_watch_id)
{
- 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?
+ g_bus_unwatch_name (m_bus_watch_id);
+ m_bus_watch_id = 0;
}
- 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
+ if (m_properties_changed_id)
{
- 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());
+ g_signal_handler_disconnect(m_proxy, m_properties_changed_id);
+ m_properties_changed_id = 0;
}
- reload();
+ g_clear_object(&m_proxy);
+ g_clear_pointer(&m_loop, g_main_loop_unref);
}
- static void on_file_changed(gpointer gself)
+ static void on_properties_changed(GDBusProxy *proxy G_GNUC_UNUSED,
+ GVariant *changed_properties /* a{sv} */,
+ GStrv invalidated_properties G_GNUC_UNUSED,
+ gpointer gself)
{
- static_cast<Impl*>(gself)->reload();
+ auto self = static_cast<Impl*>(gself);
+ char *tz;
+
+ if (g_variant_lookup(changed_properties, "Timezone", "s", &tz, NULL))
+ {
+ g_debug("on_properties_changed: got timezone '%s'", tz);
+ self->notify_timezone(tz);
+ g_free (tz);
+ }
}
- void reload()
+ static void on_proxy_ready(GObject *object G_GNUC_UNUSED,
+ GAsyncResult *res,
+ gpointer gself)
{
- const auto new_timezone = get_timezone_from_file(m_filename);
+ auto self = static_cast<Impl*>(gself);
+ GError *error = nullptr;
+ self->m_proxy = g_dbus_proxy_new_finish(res, &error);
- if (!new_timezone.empty())
- m_owner.timezone.set(new_timezone);
- }
+ if (error)
+ {
+ g_warning ("Couldn't create proxy to read timezone: %s", error->message);
+ goto out;
+ }
- /***
- ****
- ***/
+ /* Read the property */
+ GVariant *prop;
+ prop = g_dbus_proxy_get_cached_property(self->m_proxy, "Timezone");
- std::string get_timezone_from_file(const std::string& filename)
- {
- GError * error;
- GIOChannel * io_channel;
- std::string ret;
-
- // read through filename line-by-line until we fine a nonempty non-comment line
- error = nullptr;
- io_channel = g_io_channel_new_file(filename.c_str(), "r", &error);
- if (error == nullptr)
+ if (!prop || !g_variant_is_of_type(prop, G_VARIANT_TYPE_STRING))
{
- auto line = g_string_new(nullptr);
-
- while(ret.empty())
- {
- const auto io_status = g_io_channel_read_line_string(io_channel, line, nullptr, &error);
- if ((io_status == G_IO_STATUS_EOF) || (io_status == G_IO_STATUS_ERROR))
- break;
- if (error != nullptr)
- break;
+ g_warning("Couldn't read the Timezone property, defaulting to Etc/Utc");
+ self->notify_timezone("Etc/Utc");
+ goto out;
+ }
- g_strstrip(line->str);
+ const gchar *tz;
+ tz = g_variant_get_string(prop, nullptr);
- if (!line->len) // skip empty lines
- continue;
+ self->notify_timezone(tz);
- if (*line->str=='#') // skip comments
- continue;
+ self->m_properties_changed_id = g_signal_connect(self->m_proxy,
+ "g-properties-changed",
+ (GCallback) on_properties_changed,
+ gself);
- ret = line->str;
- }
+out:
+ g_clear_pointer(&error, g_error_free);
+ g_clear_pointer(&prop, g_variant_unref);
+ if (self->m_loop && g_main_loop_is_running(self->m_loop))
+ g_main_loop_quit(self->m_loop);
+ }
- g_string_free(line, true);
- }
+ static void on_name_appeared(GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner G_GNUC_UNUSED,
+ gpointer gself G_GNUC_UNUSED)
+ {
+ g_debug ("timedate1 appeared");
+ g_dbus_proxy_new(connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ name,
+ "/org/freedesktop/timedate1",
+ "org.freedesktop.timedate1",
+ nullptr,
+ on_proxy_ready,
+ gself);
+ }
- if (io_channel != nullptr)
- {
- g_io_channel_shutdown(io_channel, false, nullptr);
- g_io_channel_unref(io_channel);
- }
+ static void on_name_vanished(GDBusConnection *connection G_GNUC_UNUSED,
+ const gchar *name G_GNUC_UNUSED,
+ gpointer gself)
+ {
+ auto self = static_cast<Impl*>(gself);
+ g_debug ("timedate1 vanished");
+
+ g_signal_handler_disconnect(self->m_proxy,
+ self->m_properties_changed_id);
+ self->m_properties_changed_id = 0;
+ g_clear_object(&self->m_proxy);
+ g_clear_pointer(&self->m_proxy, g_main_loop_unref);
+ }
- if (error != nullptr)
- {
- g_warning("%s Unable to read timezone file '%s': %s", G_STRLOC, filename.c_str(), error->message);
- g_error_free(error);
- }
+ void monitor_timezone_property()
+ {
+ m_bus_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM,
+ "org.freedesktop.timedate1",
+ G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+ on_name_appeared,
+ on_name_vanished,
+ this,
+ nullptr);
+
+ g_main_loop_run(m_loop);
+ }
- return ret;
+ void notify_timezone(std::string new_timezone)
+ {
+ if (!new_timezone.empty())
+ m_owner.timezone.set(new_timezone);
}
/***
@@ -165,17 +181,18 @@ private:
***/
FileTimezone & m_owner;
- std::string m_filename;
- GFileMonitor * m_monitor = nullptr;
- unsigned long m_monitor_handler_id = 0;
+ unsigned long m_properties_changed_id = 0;
+ unsigned long m_bus_watch_id = 0;
+ GDBusProxy *m_proxy = nullptr;
+ GMainLoop *m_loop = nullptr;
};
/***
****
***/
-FileTimezone::FileTimezone(const std::string& filename):
- impl(new Impl{*this, filename})
+FileTimezone::FileTimezone():
+ impl(new Impl{*this})
{
}
diff --git a/src/timezones-live.cpp b/src/timezones-live.cpp
index 4902b76..c5dd43c 100644
--- a/src/timezones-live.cpp
+++ b/src/timezones-live.cpp
@@ -25,9 +25,8 @@ namespace unity {
namespace indicator {
namespace datetime {
-LiveTimezones::LiveTimezones(const std::shared_ptr<const Settings>& settings,
- const std::string& filename):
- m_file(filename),
+LiveTimezones::LiveTimezones(const std::shared_ptr<const Settings>& settings):
+ m_file(),
m_settings(settings)
{
m_file.timezone.changed().connect([this](const std::string&){update_timezones();});