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:
Родитель
2a16ce8ff4
Коммит
1c028267c1
|
@ -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() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче