[california] Properly move event between calendars: Bug #739164



commit 3bdf39941577e50f7c73ec525d515003a5ffa4cf
Author: Jim Nelson <jim yorba org>
Date:   Wed Oct 29 17:36:31 2014 -0700

    Properly move event between calendars: Bug #739164
    
    Component.Instance allowed for callers to directly change the
    Backing.CalendarSource of an instance.  This caused comparison and
    hash problems when the event was to be removed from the view
    collections.  Now that Instance clones are used in editing, it's not
    necessary to allow changing the calendar source. Instead, the calendar
    source is simply used to create/update/delete the clone as appropriate
    and the subscription manager will report changes to the view.

 src/component/component-details-parser.vala |    3 +-
 src/component/component-event.vala          |    4 +-
 src/component/component-instance.vala       |    8 +++++-
 src/host/host-create-update-event.vala      |   21 ++++++++-----------
 src/host/host-main-window.vala              |   28 ++++++++++++--------------
 src/host/host-quick-create-event.vala       |   14 ++++++------
 6 files changed, 38 insertions(+), 40 deletions(-)
---
diff --git a/src/component/component-details-parser.vala b/src/component/component-details-parser.vala
index c16b82d..5c558db 100644
--- a/src/component/component-details-parser.vala
+++ b/src/component/component-details-parser.vala
@@ -135,8 +135,7 @@ public class DetailsParser : BaseObject {
      * If the details string is empty, a blank Event is generated.
      */
     public DetailsParser(string? details, Backing.CalendarSource? calendar_source, Event? initial = null) {
-        event = initial ?? new Component.Event.blank();
-        event.calendar_source = calendar_source;
+        event = initial ?? new Component.Event.blank(calendar_source);
         this.details = details ?? "";
         
         // pull out details from the initial Event and add to the local state, which is then
diff --git a/src/component/component-event.vala b/src/component/component-event.vala
index 00f13c8..ba1fde2 100644
--- a/src/component/component-event.vala
+++ b/src/component/component-event.vala
@@ -105,8 +105,8 @@ public class Event : Instance, Gee.Comparable<Event> {
      * A { link Calendar.DateSpan} or a { link Calendar.ExactTimeSpan} must be specified in order
      * to generate a minimally-valid Event.
      */
-    public Event.blank() {
-        base.blank(iCal.icalcomponent_kind.VEVENT_COMPONENT);
+    public Event.blank(Backing.CalendarSource? calendar_source = null) {
+        base.blank(iCal.icalcomponent_kind.VEVENT_COMPONENT, calendar_source);
         
         notify.connect(on_notify);
     }
diff --git a/src/component/component-instance.vala b/src/component/component-instance.vala
index aff3575..89cc3c2 100644
--- a/src/component/component-instance.vala
+++ b/src/component/component-instance.vala
@@ -47,7 +47,7 @@ public abstract class Instance : BaseObject, Gee.Hashable<Instance> {
      *
      * This will initialize as null if created as a { link blank} Instance.
      */
-    public Backing.CalendarSource? calendar_source { get; set; default = null; }
+    public Backing.CalendarSource? calendar_source { get; private set; default = null; }
     
     /**
      * The date-time stamp of the { link Instance}.
@@ -236,10 +236,11 @@ public abstract class Instance : BaseObject, Gee.Hashable<Instance> {
      *
      * Unlike the primary constructor, this will not call { link full_update}.
      */
-    protected Instance.blank(iCal.icalcomponent_kind kind) {
+    protected Instance.blank(iCal.icalcomponent_kind kind, Backing.CalendarSource? calendar_source) {
         _ical_component = new iCal.icalcomponent(kind);
         uid = Component.UID.generate();
         _ical_component.set_uid(uid.value);
+        this.calendar_source = calendar_source;
         
         notify.connect(on_notify);
     }
@@ -580,6 +581,9 @@ public abstract class Instance : BaseObject, Gee.Hashable<Instance> {
         if (sequence != other.sequence)
             return false;
         
+        if (calendar_source != other.calendar_source)
+            return false;
+        
         return uid.equal_to(other.uid);
     }
     
diff --git a/src/host/host-create-update-event.vala b/src/host/host-create-update-event.vala
index 561d91e..f6dd38b 100644
--- a/src/host/host-create-update-event.vala
+++ b/src/host/host-create-update-event.vala
@@ -57,7 +57,6 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
     
     private new Component.Event event = new Component.Event.blank();
     private EventTimeSettings.Message? dt = null;
-    private Backing.CalendarSource? original_calendar_source = null;
     private Toolkit.ComboBoxTextModel<Backing.CalendarSource> calendar_model;
     
     private Toolkit.RotatingButtonBox rotating_button_box = new Toolkit.RotatingButtonBox();
@@ -132,8 +131,6 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
             event = (Component.Event) message;
             if (dt == null)
                 dt = new EventTimeSettings.Message.from_event(event);
-            
-            original_calendar_source = event.calendar_source;
         }
         
         update_controls();
@@ -229,7 +226,6 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
     // Event's properties and update that way ... doesn't quite work when updating the master event,
     // however
     private void update_component(Component.Event target, bool replace_dtstart) {
-        target.calendar_source = calendar_model.active;
         target.summary = summary_entry.text;
         target.location = location_entry.text;
         target.description = description_textview.buffer.text;
@@ -284,7 +280,7 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
     }
     
     private async void create_event_async(Component.Event target, Cancellable? cancellable) {
-        if (target.calendar_source == null) {
+        if (calendar_model.active == null) {
             report_error(_("Unable to create event: calendar must be specified"));
             
             return;
@@ -294,7 +290,7 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
         
         Error? create_err = null;
         try {
-            yield target.calendar_source.create_component_async(target, cancellable);
+            yield calendar_model.active.create_component_async(target, cancellable);
         } catch (Error err) {
             create_err = err;
         }
@@ -308,14 +304,14 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
     }
     
     private async void update_event_async(Component.Event target, Cancellable? cancellable) {
-        if (target.calendar_source == null) {
+        if (calendar_model.active == null) {
             report_error(_("Unable to update event: calendar must be specified"));
             
             return;
         }
         
         // no original calendar source, then not an update or a move but a create
-        if (original_calendar_source == null) {
+        if (target.calendar_source == null) {
             yield create_event_async(target, cancellable);
             
             return;
@@ -324,7 +320,7 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
         Gdk.Cursor? cursor = Toolkit.set_busy(this);
         
         Error? update_err = null;
-        if (target.calendar_source == original_calendar_source) {
+        if (calendar_model.active == target.calendar_source) {
             // straight-up update
             try {
                 yield target.calendar_source.update_component_async(target, cancellable);
@@ -334,15 +330,16 @@ public class CreateUpdateEvent : Gtk.Grid, Toolkit.Card {
         } else {
             // move event from one calendar to another ... start with create on new calendar
             try {
-                yield target.calendar_source.create_component_async(target, cancellable);
+                yield calendar_model.active.create_component_async(target, cancellable);
             } catch (Error err) {
                 update_err = err;
             }
             
-            // only delete old one if new one created
+            // only delete old one if new one created ... the new one will be reported via a
+            // calendar subscription and added to the main display that way
             if (update_err == null) {
                 try {
-                    yield original_calendar_source.remove_all_instances_async(target.uid, cancellable);
+                    yield target.calendar_source.remove_all_instances_async(target.uid, cancellable);
                 } catch (Error err) {
                     update_err = err;
                 }
diff --git a/src/host/host-main-window.vala b/src/host/host-main-window.vala
index 3f01741..9ed6bb9 100644
--- a/src/host/host-main-window.vala
+++ b/src/host/host-main-window.vala
@@ -477,20 +477,8 @@ public class MainWindow : Gtk.ApplicationWindow {
         deck.go_home(event);
         
         deck.dismiss.connect(() => {
-            if (!show_event.edit_requested)
-                return;
-                
-            // pass a clone of the existing event for editing
-            Component.Event clone;
-            try {
-                clone = event.clone() as Component.Event;
-            } catch (Error err) {
-                Application.instance.error_message(this, _("Unable to edit event: %s").printf(err.message));
-                
-                return;
-            }
-            
-            edit_event(clone, true);
+            if (show_event.edit_requested)
+                edit_event(event, true);
         });
         
         show_deck_popover(relative_to, for_location, deck);
@@ -511,6 +499,16 @@ public class MainWindow : Gtk.ApplicationWindow {
     }
     
     private void on_edit_event(Component.Event event, bool is_update) {
+        // pass a clone of the existing event for editing
+        Component.Event clone;
+        try {
+            clone = event.clone() as Component.Event;
+        } catch (Error err) {
+            Application.instance.error_message(this, _("Unable to edit event: %s").printf(err.message));
+            
+            return;
+        }
+        
         CreateUpdateEvent create_update = new CreateUpdateEvent();
         create_update.is_update = is_update;
         
@@ -525,7 +523,7 @@ public class MainWindow : Gtk.ApplicationWindow {
         );
         
         // "initialize" the Deck with the requested Event
-        deck.go_home(event);
+        deck.go_home(clone);
         
         show_deck_window(deck);
     }
diff --git a/src/host/host-quick-create-event.vala b/src/host/host-quick-create-event.vala
index f55721a..92d02b3 100644
--- a/src/host/host-quick-create-event.vala
+++ b/src/host/host-quick-create-event.vala
@@ -43,11 +43,11 @@ public class QuickCreateEvent : Gtk.Grid, Toolkit.Card {
     [GtkChild]
     private Gtk.Button cancel_button;
     
-    private Toolkit.ComboBoxTextModel<Backing.CalendarSource> model;
+    private Toolkit.ComboBoxTextModel<Backing.CalendarSource> calendar_model;
     private Toolkit.EntryClearTextConnector clear_text_connector = new Toolkit.EntryClearTextConnector();
     
     public QuickCreateEvent(bool in_deck_window) {
-        model = build_calendar_source_combo_model(calendar_combo_box);
+        calendar_model = build_calendar_source_combo_model(calendar_combo_box);
         
         clear_text_connector.connect_to(details_entry);
         details_entry.bind_property("text", create_button, "sensitive", BindingFlags.SYNC_CREATE,
@@ -88,7 +88,7 @@ public class QuickCreateEvent : Gtk.Grid, Toolkit.Card {
         example_label.label = "<small><i>%s</i></small>".printf(eg);
         
         // reset calendar combo to default active item
-        model.set_item_default_active();
+        calendar_model.set_item_default_active();
     }
     
     [GtkCallback]
@@ -107,7 +107,7 @@ public class QuickCreateEvent : Gtk.Grid, Toolkit.Card {
         if (String.is_empty(details))
             return;
         
-        Component.DetailsParser parser = new Component.DetailsParser(details, model.active,
+        Component.DetailsParser parser = new Component.DetailsParser(details, calendar_model.active,
             event);
         event = parser.event;
         
@@ -123,7 +123,7 @@ public class QuickCreateEvent : Gtk.Grid, Toolkit.Card {
         // empty text okay
         string details = details_entry.text.strip();
         if (!String.is_empty(details)) {
-            Component.DetailsParser parser = new Component.DetailsParser(details, model.active,
+            Component.DetailsParser parser = new Component.DetailsParser(details, calendar_model.active,
                 event);
             event = parser.event;
         }
@@ -152,7 +152,7 @@ public class QuickCreateEvent : Gtk.Grid, Toolkit.Card {
     }
     
     private async void create_event_async(Cancellable? cancellable) {
-        if (event.calendar_source == null) {
+        if (calendar_model.active == null) {
             report_error(_("Unable to create event: calendar must be specified"));
             
             return;
@@ -162,7 +162,7 @@ public class QuickCreateEvent : Gtk.Grid, Toolkit.Card {
         
         Error? create_err = null;
         try {
-            yield event.calendar_source.create_component_async(event, cancellable);
+            yield calendar_model.active.create_component_async(event, cancellable);
         } catch (Error err) {
             create_err = err;
         }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]