Fix bug 474630 - Alarms don't work for recurring events (regression). r=philipp
authorDaniel Boelzle [:dbo] <daniel.boelzle@sun.com>
Fri, 30 Jan 2009 23:45:23 +0100
changeset 1809 04ca96e53fe28956fd45a801df763daf85b607d0
parent 1808 3d71892bdb83727b6e1d70ed2c8be429bfca0310
child 1810 cfb1a883cc47f4ab10066dcaa191fda29ce74976
push idunknown
push userunknown
push dateunknown
reviewersphilipp
bugs474630
Fix bug 474630 - Alarms don't work for recurring events (regression). r=philipp
calendar/base/content/calendar-view-core.xml
calendar/base/src/calItemBase.js
--- a/calendar/base/content/calendar-view-core.xml
+++ b/calendar/base/content/calendar-view-core.xml
@@ -186,18 +186,18 @@
           var item = this.mOccurrence;          
           this.setAttribute("item-calendar", item.calendar.uri.spec);
           var categoriesArray = item.getCategories({});
           if (categoriesArray.length > 0) {
             var cssClassesArray = categoriesArray.map(formatStringForCSSRule);
             this.setAttribute("categories", cssClassesArray.join(" "));
           }
 
-          // Add alarm icons as needed. Also add parent item alarms in case this is an occurrence.
-          let alarms = item.getAlarms({}).concat(item.parentItem.getAlarms({}));
+          // Add alarm icons as needed.
+          let alarms = item.getAlarms({});
           let iconsBox = document.getAnonymousElementByAttribute(this, "anonid", "alarm-icons-box");
           cal.alarms.addReminderImages(iconsBox, alarms);
 
           // Set suppressed status on the icons box
           setElementValue(iconsBox,
                           item.calendar.getProperty("suppressAlarms") || false,
                           "suppressed");
 
--- a/calendar/base/src/calItemBase.js
+++ b/calendar/base/src/calItemBase.js
@@ -67,17 +67,16 @@ calItemBase.prototype = {
      * Initialize the base item's attributes. Can be called from inheriting
      * objects in their constructor.
      */
     initItemBase: function cIB_initItemBase() {
         this.wrappedJSObject = this;
         this.mProperties = new calPropertyBag();
         this.mPropertyParams = {};
         this.mProperties.setProperty("CREATED", jsDateToDateTime(new Date()));
-        this.mAlarms = [];
     },
 
     /**
      * @see nsISupports
      */
     QueryInterface: function cIB_QueryInterface(aIID) {
         return doQueryInterface(this, calItemBase.prototype, aIID,
                                 [Components.interfaces.calIItemBase]);
@@ -198,29 +197,32 @@ calItemBase.prototype = {
 
         // make all our components immutable
         if (this.mRecurrenceInfo)
             this.mRecurrenceInfo.makeImmutable();
 
         if (this.mOrganizer)
             this.mOrganizer.makeImmutable();
         if (this.mAttendees) {
-            for (var i = 0; i < this.mAttendees.length; i++)
-                this.mAttendees[i].makeImmutable();
+            for each (let att in this.mAttendees) {
+                att.makeImmutable();
+            }
         }
 
         for each (let [propKey, propValue] in this.mProperties) {
             if (propValue instanceof Components.interfaces.calIDateTime &&
                 propValue.isMutable) {
                 propValue.makeImmutable();
             }
         }
 
-        for (let i = 0; i < this.mAlarms.length; i++) {
-            this.mAlarms[i].makeImmutable();
+        if (this.mAlarms) {
+            for each (let alarm in this.mAlarms) {
+                alarm.makeImmutable();
+            }
         }
 
         if (this.mAlarmLastAck) {
             this.mAlarmLastAck.makeImmutable();
         }
 
         this.ensureNotDirty();
         this.mImmutable = true;
@@ -289,20 +291,21 @@ calItemBase.prototype = {
         // xxx todo: the below two need proper cloning,
         //           calIAttachment::item, calIRelation::item are wrong
         //           bug 466439
         m.mAttachments = this.getAttachments({});
         m.mRelations = this.getRelations({});
 
         m.mCategories = this.getCategories({});
 
-        for each (let alarm in this.mAlarms) {
+        m.mAlarms = [];
+        for each (let alarm in this.getAlarms({})) {
             // Clone alarms into new item, assume the alarms from the old item
             // are valid and don't need validation.
-            m.addAlarm(alarm.clone(), true);
+            m.mAlarms.push(alarm.clone());
         }
 
         let alarmLastAck = this.alarmLastAck;
         if (alarmLastAck) {
             alarmLastAck = alarmLastAck.clone();
         }
         m.mAlarmLastAck = alarmLastAck;
 
@@ -783,25 +786,26 @@ calItemBase.prototype = {
                     rec = new calRecurrenceInfo();
                     rec.item = this;
                 }
                 rec.appendRecurrenceItem(ritem);
             }
         }
         this.mRecurrenceInfo = rec;
 
+        this.mAlarms = []; // don't inherit anything from parent
         for (let alarmComp in cal.ical.subcomponentIterator(icalcomp, "VALARM")) {
             let alarm = cal.createAlarm();
             try {
                 alarm.icalComponent = alarmComp;
                 this.addAlarm(alarm, true);
             } catch (e) {
-                Components.utils.reportError("Invalid alarm for item: " +
-                                             this.id + " (" +
-                                             alarmComp.serializeToICS() + ")");
+                cal.ERROR("Invalid alarm for item: " +
+                          this.id + " (" +
+                          alarmComp.serializeToICS() + ")");
             }
         }
 
         let lastAck = icalcomp.getFirstProperty("X-MOZ-LASTACK");
         this.mAlarmLastAck = null;
         if (lastAck) {
             this.mAlarmLastAck = cal.createDateTime(lastAck.value);
         }
@@ -907,18 +911,26 @@ calItemBase.prototype = {
     },
 
     // void getAlarms(out PRUint32 count, [array, size_is(count), retval] out calIAlarm aAlarms);
     getAlarms: function cIB_getAlarms(aCount) {
         if (typeof aCount != "object") {
             throw Components.results.NS_ERROR_XPC_NEED_OUT_OBJECT;
         }
 
-        aCount.value = this.mAlarms.length;
-        return this.mAlarms;
+        if (!this.mAlarms && this.mIsProxy) {
+            this.mAlarms = this.mParentItem.getAlarms(aCount);
+        }
+        if (this.mAlarms) {
+            aCount.value = this.mAlarms.length;
+            return this.mAlarms.concat([]); // clone
+        } else {
+            aCount.value = 0;
+            return [];
+        }
     },
 
     /**
      * Adds an alarm. The second parameter is for internal use only, i.e not
      * provided on the interface.
      *
      * @see calIItemBase
      * @param aDoNotValidate    Don't serialize the component to check for
@@ -930,24 +942,26 @@ calItemBase.prototype = {
                 // Trigger the icalComponent getter to make sure the alarm is valid.
                 aAlarm.icalComponent;
             } catch (e) {
                 throw Components.results.NS_ERROR_INVALID_ARG;
             }
         }
 
         this.modify();
+        this.mAlarms = this.getAlarms({});
         this.mAlarms.push(aAlarm);
     },
 
     // void deleteAlarm(in calIAlarm aAlarm);
     deleteAlarm: function cIB_deleteAlarm(aAlarm) {
         this.modify();
+        this.mAlarms = this.getAlarms({});
         for (let i = 0; i < this.mAlarms.length; i++) {
-            if (compareObjects(this.mAlarms[i], aAlarm, Components.interfaces.calIAlarm)) {
+            if (cal.compareObjects(this.mAlarms[i], aAlarm, Components.interfaces.calIAlarm)) {
                 this.mAlarms.splice(i, 1);
                 break;
             }
         }
     },
 
     // void clearAlarms();
     clearAlarms: function cIB_clearAlarms() {