[california] Deal with additions/removals of calendars dynamically
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california] Deal with additions/removals of calendars dynamically
- Date: Fri, 4 Apr 2014 23:33:53 +0000 (UTC)
commit 84bb02273f7cce3cc48f505de8a4dbe09d685c66
Author: Jim Nelson <jim yorba org>
Date: Fri Apr 4 16:14:59 2014 -0700
Deal with additions/removals of calendars dynamically
This also improves the Calendar Manager to use the ListBoxModel,
which is far cleaner than mucking with GtkWidgets to get to the
backing data objects.
src/backing/backing-calendar-source.vala | 4 +-
src/backing/backing-manager.vala | 37 ++++++++++++++++++---
src/backing/backing-source.vala | 30 ++++++++++++++++-
src/backing/eds/backing-eds-calendar-source.vala | 2 +-
src/host/host-create-update-event.vala | 2 +
src/manager/manager-calendar-list.vala | 38 ++++++++++++++++------
6 files changed, 92 insertions(+), 21 deletions(-)
---
diff --git a/src/backing/backing-calendar-source.vala b/src/backing/backing-calendar-source.vala
index 67ddd64..7f97a9b 100644
--- a/src/backing/backing-calendar-source.vala
+++ b/src/backing/backing-calendar-source.vala
@@ -14,8 +14,8 @@ namespace California.Backing {
*/
public abstract class CalendarSource : Source {
- protected CalendarSource(string title) {
- base (title);
+ protected CalendarSource(string id, string title) {
+ base (id, title);
}
/**
diff --git a/src/backing/backing-manager.vala b/src/backing/backing-manager.vala
index 68b38d6..d099370 100644
--- a/src/backing/backing-manager.vala
+++ b/src/backing/backing-manager.vala
@@ -24,6 +24,20 @@ public class Manager : BaseObject {
*/
public signal void open_store_failed(Store store, Error err);
+ /**
+ * Fired when a { link Store} adds a new { link Source}.
+ *
+ * @see Source.source_added
+ */
+ public signal void source_added(Store store, Source source);
+
+ /**
+ * Fired when a { link Store} removes a { link Source}.
+ *
+ * @see Source.source_removed
+ */
+ public signal void source_removed(Store store, Source source);
+
private Manager() {
}
@@ -57,12 +71,18 @@ public class Manager : BaseObject {
public async int open_async(Cancellable? cancellable) throws Error {
int count = 0;
foreach (Store store in stores) {
+ store.source_added.connect(on_source_added);
+ store.source_removed.connect(on_source_removed);
+
try {
yield store.open_async(cancellable);
assert(store.is_open);
count++;
} catch (Error err) {
+ store.source_added.disconnect(on_source_added);
+ store.source_removed.disconnect(on_source_removed);
+
// treat cancelled as cancelled
if (err is IOError.CANCELLED)
throw err;
@@ -85,6 +105,9 @@ public class Manager : BaseObject {
*/
public async void close_async(Cancellable? cancellable) throws Error {
foreach (Store store in stores) {
+ store.source_added.disconnect(on_source_added);
+ store.source_removed.disconnect(on_source_removed);
+
try {
if (store.is_open) {
yield store.close_async(cancellable);
@@ -102,6 +125,14 @@ public class Manager : BaseObject {
is_open = false;
}
+ private void on_source_added(Store store, Source source) {
+ source_added(store, source);
+ }
+
+ private void on_source_removed(Store store, Source source) {
+ source_removed(store, source);
+ }
+
/**
* Returns a read-only list of all available { link Store}s.
*
@@ -128,8 +159,6 @@ public class Manager : BaseObject {
/**
* Returns a list of all available { link Source}s of a particular type.
*
- * The list will be sorted by the Sources title in lexiographic order.
- *
* Must only be called while the { link Manager} is open.
*
* @see Store.get_sources_of_type
@@ -139,10 +168,6 @@ public class Manager : BaseObject {
foreach (Store store in stores)
sources.add_all(store.get_sources_of_type<G>());
- sources.sort((a, b) => {
- return String.stricmp(((Source) a).title, ((Source) b).title);
- });
-
return sources;
}
diff --git a/src/backing/backing-source.vala b/src/backing/backing-source.vala
index 80c9498..c45625f 100644
--- a/src/backing/backing-source.vala
+++ b/src/backing/backing-source.vala
@@ -16,13 +16,20 @@ namespace California.Backing {
* @see Manager
*/
-public abstract class Source : BaseObject {
+public abstract class Source : BaseObject, Gee.Comparable<Source> {
public const string PROP_IS_AVAILABLE = "is-available";
public const string PROP_TITLE = "title";
public const string PROP_VISIBLE = "visible";
public const string PROP_COLOR = "color";
/**
+ * A unique identifier for the { link Source}.
+ *
+ * This value is persisted by the Source's { link Backing.Store}.
+ */
+ public string id { get; private set; }
+
+ /**
* True if the { link Source} is unavailable for use due to being removed from it's
* { link Backing.Store}.
*
@@ -56,7 +63,8 @@ public abstract class Source : BaseObject {
*/
public string color { get; set; }
- protected Source(string title) {
+ protected Source(string id, string title) {
+ this.id = id;
this.title = title;
}
@@ -98,6 +106,24 @@ public abstract class Source : BaseObject {
color = Gfx.rgb_to_uint8_rgb_string(Gfx.rgba_to_rgb(rgba));
}
+ /**
+ * The natural comparator for { link Source}s.
+ *
+ * The natural comparator uses the { link title} (compared case-insensitively) then the
+ * { link id} to stabilize the sort.
+ */
+ public virtual int compare_to(Source other) {
+ if (this == other)
+ return 0;
+
+ int compare = String.stricmp(title, other.title);
+ if (compare != 0)
+ return compare;
+
+ // use the Source's id to stabilize the sort
+ return strcmp(id, other.id);
+ }
+
public override string to_string() {
return title;
}
diff --git a/src/backing/eds/backing-eds-calendar-source.vala
b/src/backing/eds/backing-eds-calendar-source.vala
index a772325..35a2966 100644
--- a/src/backing/eds/backing-eds-calendar-source.vala
+++ b/src/backing/eds/backing-eds-calendar-source.vala
@@ -20,7 +20,7 @@ internal class EdsCalendarSource : CalendarSource {
private Cancellable? source_write_cancellable = null;
public EdsCalendarSource(E.Source eds_source, E.SourceCalendar eds_calendar) {
- base (eds_source.display_name);
+ base (eds_source.uid, eds_source.display_name);
this.eds_source = eds_source;
this.eds_calendar = eds_calendar;
diff --git a/src/host/host-create-update-event.vala b/src/host/host-create-update-event.vala
index 7e8530a..4e4d3e0 100644
--- a/src/host/host-create-update-event.vala
+++ b/src/host/host-create-update-event.vala
@@ -169,6 +169,8 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
// initialize available calendars
calendar_sources = Backing.Manager.instance.get_sources_of_type<Backing.CalendarSource>();
+ calendar_sources.sort();
+
index = 0;
int calendar_source_index = 0;
Gee.Iterator<Backing.Source> iter = calendar_sources.iterator();
diff --git a/src/manager/manager-calendar-list.vala b/src/manager/manager-calendar-list.vala
index 5d1ce98..e7ccb33 100644
--- a/src/manager/manager-calendar-list.vala
+++ b/src/manager/manager-calendar-list.vala
@@ -25,16 +25,27 @@ public class CalendarList : Gtk.Grid, Toolkit.Card {
[GtkChild]
private Gtk.ListBox calendar_list_box;
+ private Toolkit.ListBoxModel<Backing.CalendarSource> model;
+
public CalendarList() {
+ model = new Toolkit.ListBoxModel<Backing.CalendarSource>(calendar_list_box, model_presentation);
+
// if already open, initialize now
if (Backing.Manager.instance.is_open)
init();
+ // use Manager's signals to add and remove from model
+ Backing.Manager.instance.source_added.connect(on_source_added_to_manager);
+ Backing.Manager.instance.source_removed.connect(on_source_removed_from_manager);
+
// otherwise, initialize when it does open
Backing.Manager.instance.notify[Backing.Manager.PROP_IS_OPEN].connect(on_manager_opened_closed);
}
~CalendarList() {
+ Backing.Manager.instance.source_added.disconnect(on_source_added_to_manager);
+ Backing.Manager.instance.source_removed.disconnect(on_source_removed_from_manager);
+
Backing.Manager.instance.notify[Backing.Manager.PROP_IS_OPEN].disconnect(on_manager_opened_closed);
}
@@ -45,23 +56,30 @@ public class CalendarList : Gtk.Grid, Toolkit.Card {
if (Backing.Manager.instance.is_open)
init();
else
- clear();
+ model.clear();
}
private void init() {
assert(Backing.Manager.instance.is_open);
- foreach (Backing.CalendarSource source in
- Backing.Manager.instance.get_sources_of_type<Backing.CalendarSource>()) {
- calendar_list_box.add(new CalendarListItem(source));
- }
+ model.clear();
+ model.add_many(Backing.Manager.instance.get_sources_of_type<Backing.CalendarSource>());
+ }
+
+ private Gtk.Widget model_presentation(Backing.CalendarSource calendar) {
+ return new CalendarListItem(calendar);
+ }
+
+ private void on_source_added_to_manager(Backing.Store store, Backing.Source source) {
+ Backing.CalendarSource? calendar = source as Backing.CalendarSource;
+ if (calendar != null)
+ model.add(calendar);
}
- private void clear() {
- foreach (unowned Gtk.Widget child in calendar_list_box.get_children()) {
- if (child is CalendarListItem)
- calendar_list_box.remove(child);
- };
+ private void on_source_removed_from_manager(Backing.Store store, Backing.Source source) {
+ Backing.CalendarSource? calendar = source as Backing.CalendarSource;
+ if (calendar != null)
+ model.remove(calendar);
}
[GtkCallback]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]