[california/wip/734698-agenda] Move start date backwards and end date forwards
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/734698-agenda] Move start date backwards and end date forwards
- Date: Fri, 5 Dec 2014 23:51:58 +0000 (UTC)
commit 436e3ce976fa09bb77eb29345ef98d717031a3ee
Author: Jim Nelson <jim yorba org>
Date: Fri Dec 5 15:51:15 2014 -0800
Move start date backwards and end date forwards
Previous and Load More, but not Next quite yet.
po/POTFILES.in | 3 +
po/POTFILES.skip | 1 +
src/Makefile.am | 2 +
.../backing-calendar-subscription-manager.vala | 55 +++++++++++++++++-
src/calendar/calendar-date.vala | 24 ++++++++
src/calendar/calendar-exact-time-span.vala | 19 ++++++
src/calendar/calendar-span.vala | 14 +++++
src/calendar/calendar.vala | 6 ++-
src/california-resources.xml | 3 +
src/rc/view-agenda-event-row.ui | 1 +
src/rc/view-agenda-load-more-row.ui | 42 ++++++++++++++
src/view/agenda/agenda-controller.vala | 60 +++++++++++++++++---
src/view/agenda/agenda-date-row.vala | 25 ++++++--
src/view/agenda/agenda-load-more-row.vala | 48 ++++++++++++++++
14 files changed, 283 insertions(+), 20 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 72e528f..15a5e19 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -28,6 +28,7 @@ src/manager/manager-calendar-list-item.vala
src/manager/manager-remove-calendar.vala
src/view/agenda/agenda-controller.vala
src/view/agenda/agenda-event-row.vala
+src/view/agenda/agenda-load-more-row.vala
src/view/month/month-controller.vala
src/view/week/week-controller.vala
[type: gettext/glade]src/rc/activator-generic-subscribe.ui
@@ -49,5 +50,7 @@ src/view/week/week-controller.vala
[type: gettext/glade]src/rc/manager-calendar-list.ui
[type: gettext/glade]src/rc/manager-calendar-list-item.ui
[type: gettext/glade]src/rc/manager-remove-calendar.ui
+[type: gettext/glade]src/rc/view-agenda-date-row.ui
[type: gettext/glade]src/rc/view-agenda-event-row.ui
+[type: gettext/glade]src/rc/view-agenda-load-more-row.ui
[type: gettext/glade]src/rc/window-menu.interface
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index 22513c9..8afa4c4 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -26,6 +26,7 @@ src/manager/manager-calendar-list-item.c
src/manager/manager-remove-calendar.c
src/view/agenda/agenda-controller.c
src/view/agenda/agenda-event-row.c
+src/view/agenda/agenda-load-more-row.c
src/view/month/month-controller.c
src/view/week/week-controller.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 8e8f029..070b25c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -174,6 +174,7 @@ california_VALASOURCES = \
view/agenda/agenda-controller.vala \
view/agenda/agenda-date-row.vala \
view/agenda/agenda-event-row.vala \
+ view/agenda/agenda-load-more-row.vala \
\
view/common/common.vala \
view/common/common-events-cell.vala \
@@ -221,6 +222,7 @@ california_RC = \
rc/manager-remove-calendar.ui \
rc/view-agenda-date-row.ui \
rc/view-agenda-event-row.ui \
+ rc/view-agenda-load-more-row.ui \
rc/window-menu.interface \
$(NULL)
diff --git a/src/backing/backing-calendar-subscription-manager.vala
b/src/backing/backing-calendar-subscription-manager.vala
index 71da1b4..b86c78d 100644
--- a/src/backing/backing-calendar-subscription-manager.vala
+++ b/src/backing/backing-calendar-subscription-manager.vala
@@ -115,6 +115,50 @@ public class CalendarSubscriptionManager : BaseObject {
}
}
+ /**
+ * Expand the { link CalendarSubscriptionManager}'s { link window} of time.
+ *
+ * expand_window() will increase the contiguous span of time being monitored for changes by the
+ * subscription manager. There is no provision for managing multiple ''fragments'' of time,
+ * only expanding the window.
+ *
+ * expand_window() should ''not'' be called until { link start_async} has completed. Results
+ * are unguaranteed if called while start_async() is executing.
+ *
+ * If expanded_time is within the current window, nothing happens.
+ */
+ public async void expand_window_async(Calendar.ExactTime expanded_time) {
+ if (expanded_time in window)
+ return;
+
+ // and create a new subscription window to cover the new span of time without overlapping
+ // existing subscription(s)
+ Calendar.ExactTimeSpan subscription_window;
+ if (expanded_time.compare_to(window.start_exact_time) < 0) {
+ subscription_window = new Calendar.ExactTimeSpan(
+ expanded_time,
+ window.start_exact_time.adjust_time(-1, Calendar.TimeUnit.SECOND)
+ );
+ } else {
+ assert(expanded_time.compare_to(window.end_exact_time) > 0);
+
+ subscription_window = new Calendar.ExactTimeSpan(
+ window.end_exact_time.adjust_time(1, Calendar.TimeUnit.SECOND),
+ expanded_time
+ );
+ }
+
+ // expand the current window ... do this before adding subscriptions so if new calendars
+ // are reported during async calls, they use the full expanded window
+ window = window.expand(expanded_time);
+
+ // create new subscriptions for the expanded span only
+ foreach (Backing.Store store in Backing.Manager.instance.get_stores()) {
+ foreach (Backing.CalendarSource calendar in store.get_sources_of_type<Backing.CalendarSource>())
+ yield add_subscription_async(calendar, subscription_window, null);
+ }
+ }
+
private void on_source_added(Backing.Source source) {
Backing.CalendarSource? calendar = source as Backing.CalendarSource;
if (calendar != null)
@@ -125,12 +169,17 @@ public class CalendarSubscriptionManager : BaseObject {
// report calendar as added to subscription
calendar_added(calendar);
- // start generating instances on this calendar
+ // add a subscription for the new calendar with existing window
+ yield add_subscription_async(calendar, window, cancellable);
+ }
+
+ private async void add_subscription_async(Backing.CalendarSource calendar,
+ Calendar.ExactTimeSpan subscription_window, Cancellable? cancellable) {
try {
// Since this might be called after the dtor has finished (cancelling the operation), don't
// touch the "this" ref unless the Error is shown not to be a cancellation
- Backing.CalendarSourceSubscription subscription = yield calendar.subscribe_async(window,
- cancellable);
+ Backing.CalendarSourceSubscription subscription = yield calendar.subscribe_async(
+ subscription_window, cancellable);
// okay to use "this" ref
subscriptions.add(subscription);
diff --git a/src/calendar/calendar-date.vala b/src/calendar/calendar-date.vala
index 1bf41ce..4ba9e43 100644
--- a/src/calendar/calendar-date.vala
+++ b/src/calendar/calendar-date.vala
@@ -62,6 +62,15 @@ public class Date : Unit<Date>, Gee.Comparable<Date>, Gee.Hashable<Date> {
NO_DAY_OF_WEEK
}
+ /**
+ * The practical earliest representable { link Date} in time.
+ */
+ public static Date earliest { get; private set; }
+
+ /**
+ * The practical latest representable { link Date} in time.
+ */
+ public static Date latest { get; private set; }
/**
* @inheritDoc
@@ -145,6 +154,21 @@ public class Date : Unit<Date>, Gee.Comparable<Date>, Gee.Hashable<Date> {
year = new Year.from_gdate(gdate);
}
+ internal static void init() throws CalendarError {
+ GLib.Date earliest_gdate = GLib.Date();
+ earliest_gdate.set_julian(1);
+ earliest = new Date.from_gdate(earliest_gdate);
+
+ // GLib.Date.set_julian(uint.MAX) causes strange assertions inside of GLib, so just jimmying
+ // together a date far in the future for now
+ latest = new Date(DayOfMonth.for(31), Month.DEC, new Year(100000));
+ }
+
+ internal static void terminate() {
+ earliest = null;
+ latest = null;
+ }
+
/**
* Returns the { link Week} the { link Date} falls in.
*/
diff --git a/src/calendar/calendar-exact-time-span.vala b/src/calendar/calendar-exact-time-span.vala
index 4db2ca1..6e4a0b2 100644
--- a/src/calendar/calendar-exact-time-span.vala
+++ b/src/calendar/calendar-exact-time-span.vala
@@ -140,6 +140,25 @@ public class ExactTimeSpan : BaseObject, Gee.Comparable<ExactTimeSpan>, Gee.Hash
}
/**
+ * Returns an { link ExactTimeSpan} expanded to include the supplied { link ExactTime}.
+ *
+ * If the expanded_time is within this ExactTimeSpan, this object is returned.
+ */
+ public ExactTimeSpan expand(ExactTime expanded_time) {
+ if (contains(expanded_time))
+ return this;
+
+ // if supplied time before start of span, that becomes the new start time
+ if (expanded_time.compare_to(start_exact_time) < 0)
+ return new ExactTimeSpan(expanded_time, end_exact_time);
+
+ // prior tests guarantee supplied time is after end of this span
+ assert(expanded_time.compare_to(end_exact_time) > 0);
+
+ return new ExactTimeSpan(start_exact_time, expanded_time);
+ }
+
+ /**
* Returns a prettified string describing the { link Event}'s time span in as concise and
* economical manner possible.
*
diff --git a/src/calendar/calendar-span.vala b/src/calendar/calendar-span.vala
index 2f7eaeb..30d2997 100644
--- a/src/calendar/calendar-span.vala
+++ b/src/calendar/calendar-span.vala
@@ -180,6 +180,20 @@ public abstract class Span : BaseObject {
}
/**
+ * Returns a { link DateSpan} that covers the time of this { link Span} and the supplied
+ * { link Date}.
+ *
+ * If the Date is within the existing Span, a DateSpan for this Span is returned, i.e. this
+ * is just like calling { link to_date_span}.
+ */
+ public DateSpan expand(Calendar.Date expansion) {
+ Date new_start = (expansion.compare_to(start_date) < 0) ? expansion : start_date;
+ Date new_end = (expansion.compare_to(end_date) > 0) ? expansion : end_date;
+
+ return new DateSpan(new_start, new_end);
+ }
+
+ /**
* True if the { link Span} contains the specified { link Date}.
*/
public bool has_date(Date date) {
diff --git a/src/calendar/calendar.vala b/src/calendar/calendar.vala
index 75cc426..09f7a83 100644
--- a/src/calendar/calendar.vala
+++ b/src/calendar/calendar.vala
@@ -233,13 +233,15 @@ public void init() throws Error {
// This init() throws an IOError, so perform before others to prevent unnecessary unwinding
System.preinit();
- // internal initialization
Collection.init();
+
+ // internal initialization
OlsonZone.init();
DayOfWeek.init();
DayOfMonth.init();
Month.init();
WallTime.init();
+ Date.init();
System.init();
Timezone.init();
}
@@ -250,11 +252,13 @@ public void terminate() {
Timezone.terminate();
System.terminate();
+ Date.terminate();
WallTime.terminate();
Month.terminate();
DayOfMonth.terminate();
DayOfWeek.terminate();
OlsonZone.terminate();
+
Collection.terminate();
}
diff --git a/src/california-resources.xml b/src/california-resources.xml
index 5a72f09..707ebd1 100644
--- a/src/california-resources.xml
+++ b/src/california-resources.xml
@@ -64,6 +64,9 @@
<file compressed="false">rc/view-agenda-event-row.ui</file>
</gresource>
<gresource prefix="/org/yorba/california">
+ <file compressed="true">rc/view-agenda-load-more-row.ui</file>
+ </gresource>
+ <gresource prefix="/org/yorba/california">
<file compressed="true">rc/window-menu.interface</file>
</gresource>
</gresources>
diff --git a/src/rc/view-agenda-event-row.ui b/src/rc/view-agenda-event-row.ui
index e8b0d0c..c4d05ed 100644
--- a/src/rc/view-agenda-event-row.ui
+++ b/src/rc/view-agenda-event-row.ui
@@ -38,6 +38,7 @@
<property name="can_focus">False</property>
<property name="label">(summary)</property>
<property name="use_markup">True</property>
+ <property name="ellipsize">end</property>
</object>
</child>
</object>
diff --git a/src/rc/view-agenda-load-more-row.ui b/src/rc/view-agenda-load-more-row.ui
new file mode 100644
index 0000000..b360c96
--- /dev/null
+++ b/src/rc/view-agenda-load-more-row.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.18.3 -->
+<interface>
+ <requires lib="gtk+" version="3.12"/>
+ <template class="CaliforniaViewAgendaLoadMoreRow" parent="GtkBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">center</property>
+ <property name="hexpand">True</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="showing_until_label">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label">Showing events until Month, Day, Year.</property>
+ <attributes>
+ <attribute name="style" value="italic"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="load_more_button">
+ <property name="label" translatable="yes" comments="As in, "Load more events"">Load
_More</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="on_load_more_button_clicked"
object="CaliforniaViewAgendaLoadMoreRow" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </template>
+</interface>
diff --git a/src/view/agenda/agenda-controller.vala b/src/view/agenda/agenda-controller.vala
index c1de5a5..66e0aba 100644
--- a/src/view/agenda/agenda-controller.vala
+++ b/src/view/agenda/agenda-controller.vala
@@ -7,6 +7,8 @@
namespace California.View.Agenda {
public class Controller : BaseObject, View.Controllable {
+ public const string PROP_CURRENT_SPAN = "current-span";
+
public const string VIEW_ID = "agenda";
private class Container : Gtk.ScrolledWindow, View.Container {
@@ -55,18 +57,21 @@ public class Controller : BaseObject, View.Controllable {
*/
public View.Palette palette { get; private set; }
+ /**
+ * Current { link Calendar.DateSpan} being displayed.
+ */
+ public Calendar.DateSpan current_span { get; private set; }
+
private Container container;
- private Calendar.DateSpan current_span;
private Backing.CalendarSubscriptionManager? subscriptions = null;
private Gtk.ListBox listbox = new Gtk.ListBox();
private Toolkit.ListBoxModel<Calendar.Date> listbox_model;
+ private LoadMoreRow load_more_row;
public Controller(View.Palette palette) {
this.palette = palette;
container = new Container(this, listbox);
- current_span = new Calendar.DateSpan(Calendar.System.today,
- Calendar.System.today.adjust_by(2, Calendar.DateUnit.MONTH));
listbox_model = new Toolkit.ListBoxModel<Calendar.Date>(listbox, model_presentation);
// Don't prelight the DateRows, as they can't be selected or activated
@@ -77,7 +82,19 @@ public class Controller : BaseObject, View.Controllable {
listbox.selection_mode = Gtk.SelectionMode.NONE;
listbox.activate_on_single_click = false;
- update_subscriptions();
+ // this will initialize current_span
+ reset_subscriptions(
+ new Calendar.DateSpan(
+ Calendar.System.today,
+ Calendar.System.today.adjust_by(2, Calendar.DateUnit.MONTH)
+ )
+ );
+
+ // LoadMoreRow is persistent and always sorts to the end of the list (see model_presentation)
+ // (need to add after setting current_span in reset_subscriptions)
+ load_more_row = new LoadMoreRow(this);
+ load_more_row.load_more.connect(on_load_more);
+ listbox_model.add(Calendar.Date.latest);
}
/**
@@ -97,12 +114,14 @@ public class Controller : BaseObject, View.Controllable {
* @inheritDoc
*/
public void previous() {
+ expand_subscriptions(current_span.start_date.adjust(-1));
}
/**
* @inheritDoc
*/
public void today() {
+ reset_subscriptions(new Calendar.DateSpan(Calendar.System.today, current_span.end_date));
}
/**
@@ -120,6 +139,9 @@ public class Controller : BaseObject, View.Controllable {
}
private Gtk.Widget model_presentation(Calendar.Date date) {
+ if (date.equal_to(Calendar.Date.latest))
+ return load_more_row;
+
DateRow date_row = new DateRow(this, date);
date_row.empty.connect(on_date_row_empty);
@@ -130,7 +152,15 @@ public class Controller : BaseObject, View.Controllable {
listbox_model.remove(date_row.date);
}
- private void update_subscriptions() {
+ private void on_load_more() {
+ expand_subscriptions(current_span.end_date.adjust_by(1, Calendar.DateUnit.MONTH));
+ }
+
+ private void reset_subscriptions(Calendar.DateSpan new_span) {
+ current_span = new_span;
+
+ listbox_model.clear();
+
subscriptions = new Backing.CalendarSubscriptionManager(
current_span.to_exact_time_span(Calendar.Timezone.local));
@@ -141,13 +171,25 @@ public class Controller : BaseObject, View.Controllable {
subscriptions.start_async.begin();
- current_label = current_span.to_pretty_string(
- Calendar.Date.PrettyFlag.COMPACT
+ update_view_details();
+ }
+
+ private void expand_subscriptions(Calendar.Date expansion) {
+ current_span = current_span.expand(expansion);
+
+ subscriptions.expand_window_async.begin(
+ expansion.to_exact_time_span(Calendar.Timezone.local).start_exact_time);
+
+ update_view_details();
+ }
+
+ private void update_view_details() {
+ current_label = current_span.start_date.to_pretty_string(
+ Calendar.Date.PrettyFlag.ABBREV
| Calendar.Date.PrettyFlag.INCLUDE_YEAR
- | Calendar.Date.PrettyFlag.NO_DAY_OF_WEEK
| Calendar.Date.PrettyFlag.NO_TODAY
);
- is_viewing_today = Calendar.System.today in current_span;
+ is_viewing_today = current_span.start_date.equal_to(Calendar.System.today);
}
private void on_calendar_added(Backing.CalendarSource calendar) {
diff --git a/src/view/agenda/agenda-date-row.vala b/src/view/agenda/agenda-date-row.vala
index cdc73b4..18781c3 100644
--- a/src/view/agenda/agenda-date-row.vala
+++ b/src/view/agenda/agenda-date-row.vala
@@ -41,10 +41,17 @@ private class DateRow : Gtk.Box {
Toolkit.prevent_prelight(row);
});
- date_label.label = date.to_pretty_string(DATE_PRETTY_FLAGS);
-
// all date labels are same width
date_label_size_group.add_widget(date_label);
+
+ // Because some date text labels are relative (i.e. "Today"), refresh when the date changes
+ Calendar.System.instance.today_changed.connect(update_ui);
+
+ update_ui();
+ }
+
+ ~DateRow() {
+ Calendar.System.instance.today_changed.disconnect(update_ui);
}
internal static void init() {
@@ -55,6 +62,10 @@ private class DateRow : Gtk.Box {
date_label_size_group = null;
}
+ private void update_ui() {
+ date_label.label = date.to_pretty_string(DATE_PRETTY_FLAGS);
+ }
+
private void on_listbox_model_size_changed() {
if (listbox_model.size == 0)
empty();
@@ -65,19 +76,19 @@ private class DateRow : Gtk.Box {
return;
// watch for date changes, which affect if the event is represented here
- event.notify[Component.Event.PROP_DATE_SPAN].connect(on_date_changed);
- event.notify[Component.Event.PROP_EXACT_TIME_SPAN].connect(on_date_changed);
+ event.notify[Component.Event.PROP_DATE_SPAN].connect(on_event_date_changed);
+ event.notify[Component.Event.PROP_EXACT_TIME_SPAN].connect(on_event_date_changed);
}
public void remove_event(Component.Event event) {
if (!listbox_model.remove(event))
return;
- event.notify[Component.Event.PROP_DATE_SPAN].disconnect(on_date_changed);
- event.notify[Component.Event.PROP_EXACT_TIME_SPAN].disconnect(on_date_changed);
+ event.notify[Component.Event.PROP_DATE_SPAN].disconnect(on_event_date_changed);
+ event.notify[Component.Event.PROP_EXACT_TIME_SPAN].disconnect(on_event_date_changed);
}
- private void on_date_changed(Object o, ParamSpec pspec) {
+ private void on_event_date_changed(Object o, ParamSpec pspec) {
Component.Event event = (Component.Event) o;
if (!(date in event.get_event_date_span(Calendar.Timezone.local)))
diff --git a/src/view/agenda/agenda-load-more-row.vala b/src/view/agenda/agenda-load-more-row.vala
new file mode 100644
index 0000000..5c1d65a
--- /dev/null
+++ b/src/view/agenda/agenda-load-more-row.vala
@@ -0,0 +1,48 @@
+/* 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.View.Agenda {
+
+[GtkTemplate (ui = "/org/yorba/california/rc/view-agenda-load-more-row.ui")]
+private class LoadMoreRow : Gtk.Box {
+ private unowned Controller owner;
+
+ [GtkChild]
+ private Gtk.Label showing_until_label;
+
+ public signal void load_more();
+
+ public LoadMoreRow(Controller owner) {
+ this.owner = owner;
+
+ owner.notify[Controller.PROP_CURRENT_SPAN].connect(update_ui);
+
+ update_ui();
+ }
+
+ ~LoadMoreRow() {
+ owner.notify[Controller.PROP_CURRENT_SPAN].disconnect(update_ui);
+ }
+
+ private void update_ui() {
+ string date_str = owner.current_span.end_date.to_pretty_string(
+ Calendar.Date.PrettyFlag.INCLUDE_YEAR
+ | Calendar.Date.PrettyFlag.NO_DAY_OF_WEEK
+ | Calendar.Date.PrettyFlag.NO_TODAY
+ );
+
+ // %s is a date, i.e. "Showing events until December 5, 2014"
+ showing_until_label.label = _("Showing events until %s").printf(date_str);
+ }
+
+ [GtkCallback]
+ private void on_load_more_button_clicked() {
+ load_more();
+ }
+}
+
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]