Fix bug 345607 - Copy recurring event and paste to another day appears to work but event is not saved (has RECURRENCE-ID but no parent item) [clipboard]. r=philipp

This commit is contained in:
Daniel Boelzle [:dbo] 2009-02-14 17:08:12 +01:00
Родитель 2a16ce8ff4
Коммит 1c028267c1
7 изменённых файлов: 78 добавлений и 42 удалений

Просмотреть файл

@ -222,17 +222,7 @@ function pasteFromClipboard() {
// Set new UID to allow multiple paste actions of the same
// clipboard content.
newItem.id = cal.getUUID();
if (item.startDate) {
newItem.startDate.addDuration(offset);
newItem.endDate.addDuration(offset);
} else {
if (item.entryDate) {
newItem.entryDate.addDuration(offset);
}
if (item.dueDate) {
newItem.dueDate.addDuration(offset);
}
}
cal.shiftItem(newItem, offset);
doTransaction('add', newItem, destCal, null, null);
}
endBatchTransaction();

Просмотреть файл

@ -87,6 +87,38 @@ let cal = {
return (!tz.icalComponent && !tz.isUTC && !tz.isFloating);
},
/**
* Shifts an item by the given timely offset.
*
* @param item an item
* @param offset an offset (calIDuration)
*/
shiftItem: function cal_shiftItem(item, offset) {
// When modifying dates explicitly using the setters is important
// since those may triggers e.g. calIRecurrenceInfo::onStartDateChange
// or invalidate other properties. Moreover don't modify the date-time objects
// without cloning, because changes cannot be calculated if doing so.
if (cal.isEvent(item)) {
let date = item.startDate.clone();
date.addDuration(offset);
item.startDate = date;
date = item.endDate.clone();
date.addDuration(offset);
item.endDate = date;
} else /* isToDo */ {
if (item.entryDate) {
let date = item.entryDate.clone();
date.addDuration(offset);
item.entryDate = date;
}
if (item.dueDate) {
let date = item.dueDate.clone();
date.addDuration(offset);
item.dueDate = date;
}
}
},
/**
* Shortcut function to serialize an item (including all overridden items).
*/

Просмотреть файл

@ -72,6 +72,13 @@ interface calIRecurrenceInfo : nsISupports
*/
void onStartDateChange(in calIDateTime aNewStartTime, in calIDateTime aOldStartTime);
/**
* If the base item's UID changes, this implicitly has to change all overridden items' UID, too.
*
* @param id new UID
*/
void onIdChange(in AUTF8String aNewId);
/*
* Set of recurrence items; the order of these matters.
*/

Просмотреть файл

@ -203,7 +203,7 @@ calEvent.prototype = {
}
}
this.setProperty("DTSTART", value);
return this.setProperty("DTSTART", value);
},
get startDate() {

Просмотреть файл

@ -105,7 +105,11 @@ calItemBase.prototype = {
},
set id cIB_set_id(uid) {
this.mHashId = null; // recompute hashId
return this.setProperty("UID", uid);
this.setProperty("UID", uid);
if (this.mRecurrenceInfo) {
this.mRecurrenceInfo.onIdChange(uid);
}
return uid;
},
// attribute calIDateTime recurrenceId;

Просмотреть файл

@ -38,6 +38,8 @@
*
* ***** END LICENSE BLOCK ***** */
Components.utils.import("resource://calendar/modules/calUtils.jsm");
function getRidKey(dt) {
if (!dt) {
return null;
@ -126,13 +128,13 @@ calRecurrenceInfo.prototype = {
return;
}
for each (ritem in this.mRecurrenceItems) {
for each (let ritem in this.mRecurrenceItems) {
if (ritem.isMutable) {
ritem.makeImmutable();
}
}
for each (item in this.mExceptionMap) {
for each (let item in this.mExceptionMap) {
if (item.isMutable) {
item.makeImmutable();
}
@ -172,7 +174,7 @@ calRecurrenceInfo.prototype = {
value = calTryWrappedJSObject(value);
this.mBaseItem = value;
// patch exception's parentItem:
for each (exitem in this.mExceptionMap) {
for each (let exitem in this.mExceptionMap) {
exitem.parentItem = value;
}
},
@ -763,12 +765,9 @@ calRecurrenceInfo.prototype = {
// 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 cRI_onStartDateChange(aNewStartTime, aOldStartTime) {
// passing null for the new starttime would indicate an error condition,
// since having a recurrence without a starttime is invalid.
if (!aNewStartTime) {
throw Components.results.NS_ERROR_INVALID_ARG;
}
cal.ASSERT(aNewStartTime, "invalid arg!", true);
// no need to check for changes if there's no previous starttime.
if (!aOldStartTime) {
@ -776,37 +775,36 @@ calRecurrenceInfo.prototype = {
}
// convert both dates to UTC since subtractDate is not timezone aware.
var timeDiff = aNewStartTime.getInTimezone(UTC()).subtractDate(aOldStartTime.getInTimezone(UTC()));
let timeDiff = aNewStartTime.getInTimezone(UTC()).subtractDate(aOldStartTime.getInTimezone(UTC()));
var rdates = {};
let rdates = {};
// take RDATE's and EXDATE's into account.
const kCalIRecurrenceDate = Components.interfaces.calIRecurrenceDate;
const kCalIRecurrenceDateSet = Components.interfaces.calIRecurrenceDateSet;
var ritems = this.getRecurrenceItems({});
for each (var ritem in ritems) {
if (calInstanceOf(ritem, kCalIRecurrenceDate)) {
let ritems = this.getRecurrenceItems({});
for each (let ritem in ritems) {
if (cal.calInstanceOf(ritem, kCalIRecurrenceDate)) {
ritem = ritem.QueryInterface(kCalIRecurrenceDate);
var date = ritem.date;
let date = ritem.date;
date.addDuration(timeDiff);
if (!ritem.isNegative) {
rdates[getRidKey(date)] = date;
}
ritem.date = date;
} else if (calInstanceOf(ritem, kCalIRecurrenceDateSet)) {
} else if (cal.calInstanceOf(ritem, kCalIRecurrenceDateSet)) {
ritem = ritem.QueryInterface(kCalIRecurrenceDateSet);
var rdates = ritem.getDates({});
for each (var date in rdates) {
for each (let date in ritem.getDates({})) {
date.addDuration(timeDiff);
if (!ritem.isNegative) {
rdates[getRidKey(date)] = date;
}
}
ritem.setDates(rdates.length,rdates);
} else if (calInstanceOf(ritem, Components.interfaces.calIRecurrenceRule)) {
} else if (cal.calInstanceOf(ritem, Components.interfaces.calIRecurrenceRule)) {
ritem = ritem.QueryInterface(Components.interfaces.calIRecurrenceRule);
if (!ritem.isByCount) {
var endDate = ritem.endDate;
let endDate = ritem.endDate;
if (endDate) {
endDate.addDuration(timeDiff);
ritem.endDate = endDate;
@ -815,28 +813,33 @@ calRecurrenceInfo.prototype = {
}
}
var startTimezone = aNewStartTime.timezone;
var exceptions = this.getExceptionIds({});
var modifiedExceptions = [];
for each (var exid in exceptions) {
let startTimezone = aNewStartTime.timezone;
let modifiedExceptions = [];
for each (let exid in this.getExceptionIds({})) {
let ex = this.getExceptionFor(exid);
if (ex) {
ex = ex.clone();
// track RECURRENCE-IDs in DTSTART's or RDATE's timezone,
// otherwise those won't match any longer w.r.t DST:
var rid = ex.recurrenceId;
rid = rid.getInTimezone(rdates[getRidKey(rid)]
? rdates[getRidKey(rid)].timezone
: startTimezone);
let rid = ex.recurrenceId;
let rdate = rdates[getRidKey(rid)];
rid = rid.getInTimezone(rdate ? rdate.timezone : startTimezone);
rid.addDuration(timeDiff);
ex.recurrenceId = rid;
cal.shiftItem(ex, timeDiff);
modifiedExceptions.push(ex);
this.removeExceptionFor(exid);
}
}
for each (var modifiedEx in modifiedExceptions) {
for each (let modifiedEx in modifiedExceptions) {
this.modifyException(modifiedEx, true);
}
},
onIdChange: function cRI_onIdChange(aNewId) {
// patch all overridden items' id:
for each (let item in this.mExceptionMap) {
item.id = aNewId;
}
}
};

Просмотреть файл

@ -232,7 +232,7 @@ calTodo.prototype = {
}
}
this.setProperty("DTSTART", value);
return this.setProperty("DTSTART", value);
},
get entryDate() {