[california/wip/timezone] Flesh out Calendar.System and Calendar.Timezone
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/timezone] Flesh out Calendar.System and Calendar.Timezone
- Date: Fri, 7 Mar 2014 01:19:02 +0000 (UTC)
commit 68bd18818ed4925c4fa62170bf416893f7b27398
Author: Jim Nelson <jim yorba org>
Date: Thu Mar 6 17:17:28 2014 -0800
Flesh out Calendar.System and Calendar.Timezone
src/Makefile.am | 4 +
src/calendar/calendar-dbus.vala | 58 +++++++++++++++++++
src/calendar/calendar-olson-zone.vala | 66 +++++++++++++++++++++
src/calendar/calendar-system.vala | 98 +++++++++++++++++++++++++++----
src/calendar/calendar-timezone.vala | 63 ++++++++++----------
src/calendar/calendar.vala | 22 ++-----
src/component/component-instance.vala | 2 +-
src/component/component-uid.vala | 2 +-
src/host/host-create-update-event.vala | 4 +-
src/host/host-main-window.vala | 2 +-
src/host/host-show-event.vala | 4 +-
src/view/month/month-cell.vala | 2 +-
src/view/month/month-controllable.vala | 14 ++--
13 files changed, 266 insertions(+), 75 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index a74ca36..e8942d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,13 +32,17 @@ california_VALASOURCES = \
calendar/calendar-day-of-month.vala \
calendar/calendar-day-of-week.vala \
calendar/calendar-date.vala \
+ calendar/calendar-dbus.vala \
calendar/calendar-error.vala \
calendar/calendar-exact-time.vala \
calendar/calendar-exact-time-span.vala \
calendar/calendar-first-of-week.vala \
calendar/calendar-month.vala \
calendar/calendar-month-of-year.vala \
+ calendar/calendar-olson-zone.vala \
calendar/calendar-span.vala \
+ calendar/calendar-system.vala \
+ calendar/calendar-timezone.vala \
calendar/calendar-unit.vala \
calendar/calendar-wall-time.vala \
calendar/calendar-week.vala \
diff --git a/src/calendar/calendar-dbus.vala b/src/calendar/calendar-dbus.vala
new file mode 100644
index 0000000..aa1de83
--- /dev/null
+++ b/src/calendar/calendar-dbus.vala
@@ -0,0 +1,58 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+/**
+ * D-Bus interfaces needed for system time/date information.
+ */
+
+namespace California.Calendar.DBus {
+
+/**
+ * D-Bus interface to systemd-timedated which holds various useful time/date-related information.
+ *
+ * See [[http://www.freedesktop.org/wiki/Software/systemd/timedated/]]
+ */
+
+[DBus (name = "org.freedesktop.timedate1")]
+public interface timedated : Object {
+ public const string NAME = "org.freedesktop.timedate1";
+ public const string OBJECT_PATH = "/org/freedesktop/timedate1";
+
+ public const string PROP_TIMEZONE = "Timezone";
+ public const string PROP_LOCAL_RTC = "LocalRTC";
+ public const string PROP_NTP = "NTP";
+
+ public abstract string timezone { owned get; }
+ public abstract bool local_rtc { get; }
+ public abstract bool ntp { get; }
+
+ public abstract void set_time(int64 usec_etc, bool relative, bool user_interaction) throws IOError;
+ public abstract void set_timezone(string timezone, bool user_interaction) throws IOError;
+ public abstract void set_local_rtc(bool local_rtc, bool fix_system, bool user_interaction)
+ throws IOError;
+ public abstract void set_ntp(bool use_ntp, bool user_interaction) throws IOError;
+}
+
+/**
+ * D-Bus interface for querying and monitoring properties.
+ *
+ * See [[https://pythonhosted.org/txdbus/dbus_overview.html]], "org.freedesktop.DBus.Properties"
+ */
+
+[DBus (name = "org.freedesktop.DBus.Properties")]
+public interface Properties : Object {
+ public const string NAME = "org.freedesktop.DBus.Properties";
+
+ public signal void properties_changed(string interf, HashTable<string, Variant>
changed_properties_values,
+ string[] changed_properties);
+
+ public abstract Variant get(string interf, string property) throws IOError;
+ public abstract void get_all(string interf, HashTable<string, Variant> properties) throws IOError;
+ public abstract void set(string interf, string property, Variant value) throws IOError;
+}
+
+}
+
diff --git a/src/calendar/calendar-olson-zone.vala b/src/calendar/calendar-olson-zone.vala
new file mode 100644
index 0000000..2d21ddb
--- /dev/null
+++ b/src/calendar/calendar-olson-zone.vala
@@ -0,0 +1,66 @@
+/* Copyright 2014 Yorba Foundation
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+namespace California.Calendar {
+
+/**
+ * The Olson name of a time zone in the tz (or zoneinfo) database.
+ *
+ * An Olson name is in the form of "Area/Location". This class merely encapsulates this string
+ * and gives it some type-ness; actual time zone calculations is left to { link Timezone}.
+ * In particular, little to no error-checking is performed by this class. At the moment, the
+ * class looks for perverse input and defaults to UTC. It also does no processing or consideration
+ * for zone aliases ("links"), which is why it does not implement Gee.Hashable or Gee.Comparable.
+ *
+ * This class is immutable.
+ *
+ * Future expansion may include some processing or parsing of the name itself, but that's not
+ * planned at the moment.
+ *
+ * The IANA database of Olson zones and related information is located at
+ * [[https://www.iana.org/time-zones]]
+ */
+
+public class OlsonZone : BaseObject {
+ /**
+ * The string value this class uses if an empty string is passed to the constructor.
+ *
+ * Note that this is not the only definition of UTC in the zoneinfo database. That is,
+ * a simple comparison of { link value} to this constant is no guarantee that an
+ * { link OlsonZone} is or is not UTC.
+ */
+ public const string UTC = "UTC";
+
+ /**
+ * An { link OlsonZone} representation of UTC.
+ *
+ * @see UTC
+ */
+ public static OlsonZone utc { get; private set; }
+
+ /**
+ * The raw Olson zoneinfo name.
+ */
+ public string value { get; private set; }
+
+ public OlsonZone(string area_location) {
+ value = !String.is_empty(area_location) ? area_location : UTC;
+ }
+
+ internal static void init() {
+ utc = new OlsonZone(UTC);
+ }
+
+ internal static void terminate() {
+ utc = null;
+ }
+
+ public override string to_string() {
+ return value;
+ }
+}
+
+}
diff --git a/src/calendar/calendar-system.vala b/src/calendar/calendar-system.vala
index fbf37d0..a75d02e 100644
--- a/src/calendar/calendar-system.vala
+++ b/src/calendar/calendar-system.vala
@@ -8,28 +8,86 @@ namespace California.Calendar {
/**
* A singleton offering system-based calendar and time information and updates of important changes.
+ *
+ * Most of System's properties are static as a convenience for callers (to avoid having to always
+ * reference { link instance}). Since static properties have no notification mechanism, callers
+ * interested in being notified of changes must subscribe to the instance's particular signals,
+ * i.e. { link zone_changed}.
*/
-public class System {
- public const string PROP_LOCAL_TZ = "local-tz";
-
+public class System : BaseObject {
public static System instance { get; private set; }
/**
- * The current local { link Timezone}.
+ * The current date according to the local timezone.
*
- * Since this can change at runtime, the property should ne monitored for changes.
+ * TODO: This currently does not update as the program executes.
+ */
+ public static Date today { get; private set; }
+
+ /**
+ * Returns the current { link ExactTime} of the local TimeZone.
*/
- public Timezone local_tz { get; private set; }
+ public static ExactTime now {
+ owned get {
+ return new ExactTime.now(new TimeZone.local());
+ }
+ }
/**
* If the current user is configured to use 12 or 24-hour time.
*/
- public bool is_24hr { get; private set; }
+ public static bool is_24hr { get; private set; }
+
+ /**
+ * Returns the system's configured zone as an { link OlsonZone}.
+ */
+ public static OlsonZone zone { get; private set; }
+
+ /**
+ * The current system { link Timezone}.
+ *
+ * @see local_timezone_changed
+ * @see Timezone.utc
+ */
+ public static Timezone local_timezone { get; private set; }
+
+ private static DBus.timedated timedated_service;
+ private static DBus.Properties timedated_properties;
+
+ /**
+ * Fired when { link zone} changes.
+ *
+ * This generally indicates that the user has changed system time zone manually or that the
+ * system detected the change through geolocation services.
+ */
+ public signal void zone_changed(OlsonZone new_zone);
+
+ /**
+ * Fired when { link local_timezone} changes due to system configuration changes.
+ */
+ public signal void local_timezone_changed(Timezone new_local_timezone);
private System() {
- // TODO: Fetch from GNOME settings
+ zone = new OlsonZone(timedated_service.timezone);
+ local_timezone = new Timezone(zone);
+ debug("Local zone: %s", zone.to_string());
+
+ // to be notified of changes as they occur
+ timedated_properties.properties_changed.connect(on_timedated_properties_changed);
+
+ // TODO: Fetch and update from GNOME settings
is_24hr = false;
+
+ // TODO: Tie this into the event loop so it's properly updated
+ today = new Date.now(new TimeZone.local());
+ }
+
+ internal static void preinit() throws IOError {
+ timedated_service = Bus.get_proxy_sync(BusType.SYSTEM, DBus.timedated.NAME,
+ DBus.timedated.OBJECT_PATH);
+ timedated_properties = Bus.get_proxy_sync(BusType.SYSTEM, DBus.Properties.NAME,
+ DBus.timedated.OBJECT_PATH);
}
internal static void init() {
@@ -38,13 +96,27 @@ public class System {
internal static void terminate() {
instance = null;
+ timedated_service = null;
+ timedated_properties = null;
}
- /**
- * Returns the current { link ExactTime} of the local TimeZone.
- */
- public ExactTime now() {
- return new ExactTime.now(new TimeZone.local());
+ private void on_timedated_properties_changed(string interf,
+ HashTable<string, Variant> changed_properties_values, string[] changed_properties) {
+ if (changed_properties_values.contains(DBus.timedated.PROP_TIMEZONE)
+ || DBus.timedated.PROP_TIMEZONE in changed_properties) {
+ zone = new OlsonZone(timedated_service.timezone);
+ local_timezone = new Timezone(zone);
+ debug("New local zone: %s", zone.to_string());
+
+ // fire signals last in case a subscriber monitoring zone thinks that local_timezone
+ // has also changed
+ zone_changed(zone);
+ local_timezone_changed(local_timezone);
+ }
+ }
+
+ public override string to_string() {
+ return get_class().get_type().name();
}
}
diff --git a/src/calendar/calendar-timezone.vala b/src/calendar/calendar-timezone.vala
index 22d38bf..773997a 100644
--- a/src/calendar/calendar-timezone.vala
+++ b/src/calendar/calendar-timezone.vala
@@ -6,60 +6,59 @@
namespace California.Calendar {
-public Timezone : BaseObject, Gee.Hashable<Timezone> {
- private enum Special {
- NONE,
- LOCAL,
- UTC
- }
-
+public class Timezone : BaseObject {
/**
* The { link Timezone} for UTC.
*/
public static Timezone utc { get; private set; }
/**
+ * The system's configured { link Timezone}.
+ *
+ * This is merely a convenience method for { link System.local_timezone}.
+ *
+ * @see System.local_timezone_changed
+ */
+ public static Timezone local { get { return System.local_timezone; } }
+
+ /**
+ * The { link OlsonZone} for this { link Timezone}.
+ */
+ public OlsonZone zone { get; private set; }
+
+ /**
* Returns true if this { link Timezone} represents UTC.
+ *
+ * This merely tests that this object is the same as the current { link local} object; no deep
+ * equality is tested.
*/
- public bool is_utc { get { return special == Special.UTC; } }
+ public bool is_utc { get { return this == utc; } }
/**
- * Returns true if this { link Timezone} represents the local timezone.
+ * Returns true if this { link Timezone} represents the system's configured time zone.
*
- * Since timezones may change for the computer, this returns true if the timezone was local
- * at the time the object was created.
+ * This merely tests that this object is the same as the current { link local} object; no deep
+ * equality is tested.
*/
- public bool is_local { get { return special == Special.LOCAL; } }
+ public bool is_local { get { return this == local; } }
private TimeZone tz;
- private string? identifier;
- private Special special;
- public Timezone(string identifier) {
- tz = new TimeZone(identifier);
- this.identifier = identifier;
- special = Special.NONE;
+ public Timezone(OlsonZone zone) {
+ tz = new TimeZone(zone.value);
+ this.zone = zone;
}
- private Timezone(TimeZone tz, Special special) {
- this.tz = tz;
- identifier = null;
- this.special = special;
+ internal static void init() {
+ utc = new Timezone(OlsonZone.utc);
}
- internal void init() {
- utc = new Timezone(new TimeZone.utc(), Special.UTC);
- }
-
- internal void terminate() {
+ internal static void terminate() {
utc = null;
}
- /**
- * Returns the local { link Timezone}.
- */
- public static Timezone local() {
- return new Timezone(new TimeZone.local(), Special.LOCAL);
+ public override string to_string() {
+ return zone.to_string();
}
}
diff --git a/src/calendar/calendar.vala b/src/calendar/calendar.vala
index acbbf7d..6ab23da 100644
--- a/src/calendar/calendar.vala
+++ b/src/calendar/calendar.vala
@@ -17,13 +17,6 @@
namespace California.Calendar {
-/**
- * The current date according to the local timezone.
- *
- * This currently does not update as the program executes.
- */
-public Date today;
-
private int init_count = 0;
private static unowned string FMT_MONTH_YEAR_FULL;
@@ -57,31 +50,30 @@ public void init() throws Error {
FMT_PRETTY_DATE_ABBREV = _("%a, %b %e, %Y");
FMT_PRETTY_DATE_ABBREV_NO_YEAR = _("%a, %b %e");
+ // This init() throws an IOError, so perform before others to prevent unnecessary unwinding
+ System.preinit();
+
// internal initialization
- Timezone.init();
+ OlsonZone.init();
DayOfWeek.init();
DayOfMonth.init();
Month.init();
WallTime.init();
System.init();
-
- // TODO: Tie this into the event loop so it's properly updated; also make it a property of
- // an instance so it can be monitored
- today = new Date.now(new TimeZone.local());
+ Timezone.init();
}
public void terminate() {
if (!California.Unit.do_terminate(ref init_count))
return;
- today = null;
-
+ Timezone.terminate();
System.terminate();
WallTime.terminate();
Month.terminate();
DayOfMonth.terminate();
DayOfWeek.terminate();
- Timezone.terminate();
+ OlsonZone.terminate();
}
}
diff --git a/src/component/component-instance.vala b/src/component/component-instance.vala
index 2218aa4..d2e4fcd 100644
--- a/src/component/component-instance.vala
+++ b/src/component/component-instance.vala
@@ -134,7 +134,7 @@ public abstract class Instance : BaseObject, Gee.Hashable<Instance> {
if (from_full_update)
return;
- dtstamp = Calendar.now();
+ dtstamp = Calendar.System.now;
iCal.icaltimetype ical_dtstamp = {};
exact_time_to_ical(dtstamp, &ical_dtstamp);
diff --git a/src/component/component-uid.vala b/src/component/component-uid.vala
index 63b684d..758f961 100644
--- a/src/component/component-uid.vala
+++ b/src/component/component-uid.vala
@@ -24,7 +24,7 @@ public class UID : BaseObject, Gee.Hashable<UID>, Gee.Comparable<UID> {
public static UID generate() {
// Borrowed liberally from EDS' e_cal_component_gen_uid
return new UID("%s-%d-%d-%d-%08X %s".printf(
- Calendar.now().format("%FT%H:%M:%S%z"),
+ Calendar.System.now.format("%FT%H:%M:%S%z"),
Posix.getpid(),
(int) Posix.getgid(),
(int) Posix.getppid(),
diff --git a/src/host/host-create-update-event.vala b/src/host/host-create-update-event.vala
index 0fb6511..503d91a 100644
--- a/src/host/host-create-update-event.vala
+++ b/src/host/host-create-update-event.vala
@@ -108,9 +108,9 @@ public class CreateUpdateEvent : Gtk.Grid {
all_day_toggle.active = true;
selected_date_span = event.date_span;
- initial_start_time = new Calendar.WallTime.from_exact_time(Calendar.now());
+ initial_start_time = new Calendar.WallTime.from_exact_time(Calendar.System.now);
initial_end_time = new Calendar.WallTime.from_exact_time(
- Calendar.now().adjust_time(1, Calendar.TimeUnit.HOUR));
+ Calendar.System.now.adjust_time(1, Calendar.TimeUnit.HOUR));
}
// initialize start and end time (as in, wall clock time)
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index 73619db..6673f70 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -98,7 +98,7 @@ public class MainWindow : Gtk.ApplicationWindow {
private void on_new_event() {
// create all-day event for today
- Calendar.DateSpan initial = new Calendar.DateSpan(Calendar.today, Calendar.today);
+ Calendar.DateSpan initial = new Calendar.DateSpan(Calendar.System.today, Calendar.System.today);
// revert to today's date and use the widget for the popover
create_event(null, initial, null, current_view.today(), null);
diff --git a/src/host/host-show-event.vala b/src/host/host-show-event.vala
index 151f47f..f6bf6d0 100644
--- a/src/host/host-show-event.vala
+++ b/src/host/host-show-event.vala
@@ -35,8 +35,8 @@ public class ShowEvent : Gtk.Grid {
// if any dates are not in current year, display year in all dates
Calendar.Date.PrettyFlag date_flags = Calendar.Date.PrettyFlag.NONE;
Calendar.DateSpan date_span = event.get_event_date_span();
- if (!date_span.start_date.year.equal_to(Calendar.today.year)
- || !date_span.end_date.year.equal_to(Calendar.today.year)) {
+ if (!date_span.start_date.year.equal_to(Calendar.System.today.year)
+ || !date_span.end_date.year.equal_to(Calendar.System.today.year)) {
date_flags |= Calendar.Date.PrettyFlag.INCLUDE_YEAR;
}
diff --git a/src/view/month/month-cell.vala b/src/view/month/month-cell.vala
index fce628d..61ad64c 100644
--- a/src/view/month/month-cell.vala
+++ b/src/view/month/month-cell.vala
@@ -165,7 +165,7 @@ public class Cell : Gtk.EventBox {
if (selected) {
Gdk.cairo_set_source_rgba(ctx, RGBA_SELECTED);
ctx.paint();
- } else if (date != null && date.equal_to(Calendar.today)) {
+ } else if (date != null && date.equal_to(Calendar.System.today)) {
Gdk.cairo_set_source_rgba(ctx, RGBA_CURRENT_DAY);
ctx.paint();
}
diff --git a/src/view/month/month-controllable.vala b/src/view/month/month-controllable.vala
index c6d5133..0572de8 100644
--- a/src/view/month/month-controllable.vala
+++ b/src/view/month/month-controllable.vala
@@ -108,7 +108,7 @@ public class Controllable : Gtk.Grid, View.Controllable {
notify[PROP_SHOW_OUTSIDE_MONTH].connect(update_cells);
// update now that signal handlers are in place
- month_of_year = Calendar.today.month_of_year();
+ month_of_year = Calendar.System.today.month_of_year();
first_of_week = Calendar.FirstOfWeek.SUNDAY;
}
@@ -132,13 +132,13 @@ public class Controllable : Gtk.Grid, View.Controllable {
public Gtk.Widget today() {
// since changing the date is expensive in terms of adding/removing subscriptions, only
// update the property if it's actually different
- Calendar.MonthOfYear now = Calendar.today.month_of_year();
+ Calendar.MonthOfYear now = Calendar.System.today.month_of_year();
if (!now.equal_to(month_of_year))
month_of_year = now;
- assert(date_to_cell.has_key(Calendar.today));
+ assert(date_to_cell.has_key(Calendar.System.today));
- return date_to_cell.get(Calendar.today);
+ return date_to_cell.get(Calendar.System.today);
}
/**
@@ -231,12 +231,12 @@ public class Controllable : Gtk.Grid, View.Controllable {
private void on_month_of_year_changed() {
current_label = month_of_year.full_name;
- is_viewing_today = month_of_year.equal_to(Calendar.today.month_of_year());
+ is_viewing_today = month_of_year.equal_to(Calendar.System.today.month_of_year());
// default date is first of month unless displaying current month, in which case it's
// current date
try {
- default_date = is_viewing_today ? Calendar.today
+ default_date = is_viewing_today ? Calendar.System.today
: month_of_year.date_for(month_of_year.first_day_of_month());
} catch (CalendarError calerr) {
// this should always work
@@ -405,7 +405,7 @@ public class Controllable : Gtk.Grid, View.Controllable {
// TODO: Define default time better
Calendar.ExactTime start;
- if(release_cell.date.equal_to(Calendar.today)) {
+ if(release_cell.date.equal_to(Calendar.System.today)) {
start = new Calendar.ExactTime.now(new TimeZone.local());
} else {
start = new Calendar.ExactTime(new TimeZone.local(), release_cell.date,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]