mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-30 10:12:59 +00:00
Fix issues caused by mixing "modify single occurrence" and "modify all occurrences" (bug 328084). Thanks to <michael.buettner@sun.com> for the patch; r=jminta@gmail.com
This commit is contained in:
parent
a6660394f9
commit
6b1a8e840d
@ -175,6 +175,19 @@ function getOccurrenceOrParent(occurrence) {
|
||||
return occurrence;
|
||||
}
|
||||
|
||||
// if the user wants to edit an occurrence which is already
|
||||
// an exception, always edit this single item.
|
||||
var parentItem = occurrence.parentItem;
|
||||
var rec = parentItem.recurrenceInfo;
|
||||
if (rec) {
|
||||
var exceptions = rec.getExceptionIds({});
|
||||
if (exceptions.some(function (exid) {
|
||||
return exid.compare(occurrence.recurrenceId) == 0;
|
||||
})) {
|
||||
return occurrence;
|
||||
}
|
||||
}
|
||||
|
||||
var promptService =
|
||||
Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
|
@ -63,6 +63,15 @@ interface calIRecurrenceInfo : nsISupports
|
||||
// applies, so that the start date can be tracked
|
||||
attribute calIItemBase item;
|
||||
|
||||
/**
|
||||
* The start date of an item is directly referenced by parts of calIRecurrenceInfo,
|
||||
* thus changing the former without adjusting the latter would break the internal structure.
|
||||
* This method provides the necessary functionality. There's no need to call it manually
|
||||
* after writing to the start date of an item, since it's called automatically in the
|
||||
* appropriate setter of an item.
|
||||
*/
|
||||
void onStartDateChange (in calIDateTime aNewStartTime, in calIDateTime aOldStartTime);
|
||||
|
||||
/*
|
||||
* Set of recurrence items; the order of these matters.
|
||||
*/
|
||||
|
@ -251,6 +251,27 @@ calEvent.prototype = {
|
||||
|
||||
aCount.value = 0;
|
||||
return null;
|
||||
},
|
||||
|
||||
set startDate(value) {
|
||||
this.modify();
|
||||
|
||||
// We're about to change the start date of an item which probably
|
||||
// could break the associated calIRecurrenceInfo. We're calling
|
||||
// the appropriate method here to adjust the internal structure in
|
||||
// order to free clients from worrying about such details.
|
||||
if (this.parentItem == this) {
|
||||
var rec = this.recurrenceInfo;
|
||||
if (rec) {
|
||||
rec.onStartDateChange(value,this.startDate);
|
||||
}
|
||||
}
|
||||
|
||||
this.setProperty("DTSTART", value);
|
||||
},
|
||||
|
||||
get startDate() {
|
||||
return this.getProperty("DTSTART");
|
||||
}
|
||||
};
|
||||
|
||||
@ -258,6 +279,5 @@ calEvent.prototype = {
|
||||
|
||||
var makeMemberAttr;
|
||||
if (makeMemberAttr) {
|
||||
makeMemberAttr(calEvent, "DTSTART", null, "startDate", true);
|
||||
makeMemberAttr(calEvent, "DTEND", null, "endDate", true);
|
||||
}
|
||||
|
@ -666,4 +666,54 @@ calRecurrenceInfo.prototype = {
|
||||
aCount.value = ids.length;
|
||||
return ids;
|
||||
},
|
||||
|
||||
// changing the startdate of an item needs to take exceptions into account.
|
||||
// in case we're about to modify a parentItem (aka 'folded' item), we need
|
||||
// to modify the recurrenceId's of all possibly existing exceptions as well.
|
||||
onStartDateChange: function (aNewStartTime, aOldStartTime) {
|
||||
|
||||
// convert both dates to UTC since subtractDate is not timezone aware.
|
||||
aOldStartTime = aOldStartTime.getInTimezone("UTC");
|
||||
aNewStartTime = aNewStartTime.getInTimezone("UTC");
|
||||
var timeDiff = aNewStartTime.subtractDate(aOldStartTime);
|
||||
var exceptions = this.getExceptionIds({});
|
||||
var modifiedExceptions = [];
|
||||
for each (var exid in exceptions) {
|
||||
var ex = this.getExceptionFor(exid, false);
|
||||
if (ex) {
|
||||
if (!ex.isMutable) {
|
||||
ex = ex.cloneShallow(this.item);
|
||||
}
|
||||
ex.recurrenceId.addDuration(timeDiff);
|
||||
ex.recurrenceId.normalize();
|
||||
|
||||
modifiedExceptions.push(ex);
|
||||
this.removeExceptionFor(exid);
|
||||
}
|
||||
}
|
||||
for each (var modifiedEx in modifiedExceptions) {
|
||||
this.modifyException(modifiedEx);
|
||||
}
|
||||
|
||||
// also take RDATE's and EXDATE's into account.
|
||||
const kCalIRecurrenceDate = Components.interfaces.calIRecurrenceDate;
|
||||
const kCalIRecurrenceDateSet = Components.interfaces.calIRecurrenceDateSet;
|
||||
var ritems = this.getRecurrenceItems({});
|
||||
for (var i in ritems) {
|
||||
var ritem = ritems[i];
|
||||
if (ritem instanceof kCalIRecurrenceDate) {
|
||||
ritem = ritem.QueryInterface(kCalIRecurrenceDate);
|
||||
ritem.date.addDuration(timeDiff);
|
||||
ritem.date.normalize();
|
||||
} else if (ritem instanceof kCalIRecurrenceDateSet) {
|
||||
ritem = ritem.QueryInterface(kCalIRecurrenceDateSet);
|
||||
var rdates = ritem.getDates({});
|
||||
for each (var date in rdates) {
|
||||
date.addDuration(timeDiff);
|
||||
date.normalize();
|
||||
}
|
||||
ritem.setDates(rdates.length,rdates);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -248,6 +248,27 @@ calTodo.prototype = {
|
||||
|
||||
aCount.value = 0;
|
||||
return null;
|
||||
},
|
||||
|
||||
set entryDate(value) {
|
||||
this.modify();
|
||||
|
||||
// We're about to change the start date of an item which probably
|
||||
// could break the associated calIRecurrenceInfo. We're calling
|
||||
// the appropriate method here to adjust the internal structure in
|
||||
// order to free clients from worrying about such details.
|
||||
if (this.parentItem == this) {
|
||||
var rec = this.recurrenceInfo;
|
||||
if (rec) {
|
||||
rec.onStartDateChange(value,this.entryDate);
|
||||
}
|
||||
}
|
||||
|
||||
this.setProperty("DTSTART", value);
|
||||
},
|
||||
|
||||
get entryDate() {
|
||||
return this.getProperty("DTSTART");
|
||||
}
|
||||
};
|
||||
|
||||
@ -255,7 +276,6 @@ calTodo.prototype = {
|
||||
|
||||
var makeMemberAttr;
|
||||
if (makeMemberAttr) {
|
||||
makeMemberAttr(calTodo, "DTSTART", null, "entryDate", true);
|
||||
makeMemberAttr(calTodo, "DUE", null, "dueDate", true);
|
||||
makeMemberAttr(calTodo, "COMPLETED", null, "completedDate", true);
|
||||
makeMemberAttr(calTodo, "PERCENT-COMPLETE", 0, "percentComplete", true);
|
||||
|
@ -206,8 +206,21 @@ var ltnCalendarViewController = {
|
||||
// then do so; otherwise pop up the dialog
|
||||
var itemToEdit = getOccurrenceOrParent(aOccurrence);
|
||||
if (aNewStartTime && aNewEndTime && !aNewStartTime.isDate && !aNewEndTime.isDate) {
|
||||
|
||||
var instance = itemToEdit.clone();
|
||||
|
||||
// if we're about to modify the parentItem, we need to account
|
||||
// for the possibility that the item passed as argument was
|
||||
// some other ocurrence, but the user said she would like to
|
||||
// modify all ocurrences instead.
|
||||
if (instance.parentItem == instance) {
|
||||
|
||||
var startDiff = instance.startDate.subtractDate(aOccurrence.startDate);
|
||||
aNewStartTime.addDuration(startDiff);
|
||||
var endDiff = instance.endDate.subtractDate(aOccurrence.endDate);
|
||||
aNewEndTime.addDuration(endDiff);
|
||||
}
|
||||
|
||||
instance.startDate = aNewStartTime;
|
||||
instance.endDate = aNewEndTime;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user