Fix bug 379100 - Give the Unifinder an overhaul. r=mickey

git-svn-id: svn://10.0.0.236/trunk@243731 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
mozilla%kewis.ch 2008-01-22 16:13:29 +00:00
parent ab76f38bef
commit bf3c99d1ef
8 changed files with 357 additions and 362 deletions

View File

@ -1134,13 +1134,20 @@
aEndDate = aEndDate.getInTimezone(this.mTimezone);
}
this.mStartDate = aStartDate.startOfWeek;
this.mEndDate = aEndDate.endOfWeek;
var startDate = aStartDate.startOfWeek;
var endDate = aEndDate.endOfWeek;
startDate.day += this.mWeekStartOffset;
endDate.day += this.mWeekStartOffset;
this.mStartDate.day += this.mWeekStartOffset;
this.mEndDate.day += this.mWeekStartOffset;
if (!this.mStartDate || !this.mEndDate ||
this.mStartDate.compare(startDate) != 0 ||
this.mEndDate.compare(endDate) != 0) {
// Only refresh if the date range actually changed.
this.mStartDate = startDate;
this.mEndDate = endDate;
this.refresh();
this.refresh();
}
]]></body>
</method>

View File

@ -2788,6 +2788,13 @@
// make sure unnormalized version not used below
aStartDate = aEndDate = null;
if (this.mStartDate && this.mEndDate &&
this.mStartDate.compare(startDate) == 0 &&
this.mEndDate.compare(endDate) == 0) {
// Do not change anything if the date range already matches.
return;
}
if (this.mDisplayDaysOff) {
startDate.makeImmutable();
endDate.makeImmutable();

View File

@ -148,6 +148,10 @@
var tasks = [];
var start = {};
var end = {};
if (!this.mTreeView.selection) {
return tasks;
}
var rangeCount = this.mTreeView.selection.getRangeCount();
for (var range = 0; range < rangeCount; range++) {
this.mTreeView.selection.getRangeAt(range, start, end);

View File

@ -58,73 +58,26 @@ var kEventStatusOrder = ["TENTATIVE", "CONFIRMED", "CANCELLED"];
// multiple selection
var gCalendarEventTreeClicked = false;
var gEventArray = new Array();
// Store the start and enddate, because the providers can't be trusted when
// dealing with all-day events. So we need to filter later. See bug 306157
var gStartDate;
var gEndDate;
var kDefaultTimezone;
var doingSelection = false;
var gUnifinderNeedsRefresh = true;
function resetAllowSelection() {
/**
* Do not change anything in the following lines, they are needed as
* described in the selection observer above
*/
doingSelection = false;
var searchTree = document.getElementById("unifinder-search-results-tree");
searchTree.view.selection.selectEventsSuppressed = false;
searchTree.addEventListener("select", unifinderOnSelect, true);
}
function isUnifinderHidden() {
return document.getElementById("bottom-events-box").hidden;
}
function selectSelectedEventsInTree(aEventsToSelect) {
if (doingSelection === true || isUnifinderHidden()) {
return;
}
doingSelection = true;
if (aEventsToSelect === false) {
aEventsToSelect = currentView().getSelectedItems({});
}
var searchTree = document.getElementById("unifinder-search-results-tree");
/**
* The following is a brutal hack, caused by
* http://lxr.mozilla.org/mozilla1.0/source/layout/xul/base/src/tree/src/nsTreeSelection.cpp#555
* and described in bug 168211
* http://bugzilla.mozilla.org/show_bug.cgi?id=168211
* Do NOT remove anything in the next 3 lines, or the selection in the tree will not work.
*/
searchTree.onselect = null;
searchTree.removeEventListener("select", unifinderOnSelect, true);
searchTree.view.selection.selectEventsSuppressed = true;
searchTree.view.selection.clearSelection();
if (aEventsToSelect && aEventsToSelect.length == 1) {
var rowToScrollTo = searchTree.eventView.getRowOfCalendarEvent(aEventsToSelect[0]);
if (rowToScrollTo != "null") {
searchTree.treeBoxObject.ensureRowIsVisible(rowToScrollTo);
searchTree.view.selection.timedSelect(rowToScrollTo, 1);
}
} else if (aEventsToSelect && aEventsToSelect.length > 1) {
for (var i in aEventsToSelect) {
var row = searchTree.eventView.getRowOfCalendarEvent(aEventsToSelect[i]);
searchTree.view.selection.rangedSelect(row, row, true);
}
}
// This needs to be in a setTimeout
setTimeout("resetAllowSelection()", 1);
// Extra check to see if the events are in the daterange. Some providers
// are broken when looking at all-day events.
function fixAlldayDates(aItem) {
// Using .compare on the views start and end, not on the events dates,
// because .compare uses the timezone of the datetime it is called on.
// The view's timezone is what is important here.
return ((!gEndDate || gEndDate.compare(aItem.startDate) >= 0) &&
(!gStartDate || gStartDate.compare(aItem.endDate) < 0));
}
/**
@ -161,12 +114,8 @@ var unifinderObserver = {
// produce invalid entries in the unifinder. From now on, ignore
// those operations and refresh as soon as the unifinder is shown
// again.
var unifinderTree = document.getElementById("unifinder-search-results-tree");
gUnifinderNeedsRefresh = true;
gEventArray = [];
unifinderTree.view = unifinderTreeView;
unifinderTree.eventView = new calendarEventView(gEventArray);
unifinderTreeView.clearEvents();
}
if (!this.mInBatch) {
refreshEventTree();
@ -174,38 +123,20 @@ var unifinderObserver = {
},
onAddItem: function uO_onAddItem(aItem) {
if (!(aItem instanceof Components.interfaces.calIEvent) ||
this.mInBatch ||
gUnifinderNeedsRefresh) {
return;
if (isEvent(aItem) && !this.mInBatch && !gUnifinderNeedsRefresh) {
this.addItemToTree(aItem);
}
this.addItemToTree(aItem);
},
onModifyItem: function uO_onModifyItem(aNewItem, aOldItem) {
if (this.mInBatch || gUnifinderNeedsRefresh) {
return;
}
if (aOldItem instanceof Components.interfaces.calIEvent) {
this.removeItemFromTree(aOldItem);
}
if (aNewItem instanceof Components.interfaces.calIEvent) {
this.addItemToTree(aNewItem);
}
this.onDeleteItem(aOldItem);
this.onAddItem(aNewItem);
},
onDeleteItem: function uO_onDeleteItem(aDeletedItem) {
if (!(aDeletedItem instanceof Components.interfaces.calIEvent) ||
this.mInBatch ||
gUnifinderNeedsRefresh) {
return;
if (isEvent(aDeletedItem) && !this.mInBatch && !gUnifinderNeedsRefresh) {
this.removeItemFromTree(aDeletedItem);
}
this.removeItemFromTree(aDeletedItem);
},
dateFilter: function uO_dateFilter(event) {
return ((!gEndDate || gEndDate.compare(event.startDate) >= 0) &&
(!gStartDate || gStartDate.compare(event.endDate) < 0));
},
// It is safe to call these for any event. The functions will determine
@ -217,14 +148,7 @@ var unifinderObserver = {
} else {
items = [aItem];
}
items = items.filter(this.dateFilter);
gEventArray = gEventArray.concat(items);
unifinderTreeView.sortCalendarEvents();
var tree = document.getElementById("unifinder-search-results-tree");
for each (var item in items) {
var row = tree.eventView.getRowOfCalendarEvent(item);
tree.treeBoxObject.rowCountChanged(row, 1);
}
unifinderTreeView.addItems(items.filter(fixAlldayDates));
},
removeItemFromTree: function uO_removeItemFromTree(aItem) {
var items;
@ -233,13 +157,7 @@ var unifinderObserver = {
} else {
items = [aItem];
}
items = items.filter(this.dateFilter);
var tree = document.getElementById("unifinder-search-results-tree");
for each (var item in items) {
var row = tree.eventView.getRowOfCalendarEvent(item);
gEventArray.splice(row, 1);
tree.treeBoxObject.rowCountChanged(row, -1);
}
unifinderTreeView.removeItems(items.filter(fixAlldayDates));
},
onError: function uO_onError(aErrNo, aMessage) {},
@ -267,9 +185,11 @@ var unifinderObserver = {
* Called when the calendar is loaded
*/
function prepareCalendarUnifinder() {
function onGridSelect(aEvent) {
selectSelectedEventsInTree(aEvent.detail);
}
// Only load once
window.removeEventListener("load", prepareCalendarUnifinder, false);
LOG("PREPARE UNIFINDER " + STACK());
var unifinderTree = document.getElementById("unifinder-search-results-tree");
// set up our calendar event observer
var ccalendar = getCompositeCalendar();
@ -277,13 +197,17 @@ function prepareCalendarUnifinder() {
kDefaultTimezone = calendarDefaultTimezone();
// Set up the unifinder views.
unifinderTreeView.treeElement = unifinderTree;
unifinderTree.view = unifinderTreeView;
// Listen for changes in the selected day, so we can update if need be
var viewDeck = getViewDeck();
if (viewDeck) {
viewDeck.addEventListener("dayselect", unifinderOnDaySelect, false);
viewDeck.addEventListener("itemselect", onGridSelect, true);
viewDeck.addEventListener("dayselect", unifinderDaySelect, false);
viewDeck.addEventListener("itemselect", unifinderItemSelect, true);
}
// Display something upon first load. onLoad doesn't work properly for
// observers
if (!isUnifinderHidden()) {
@ -296,17 +220,30 @@ function prepareCalendarUnifinder() {
* Called when the calendar is unloaded
*/
function finishCalendarUnifinder() {
var ccalendar = getCompositeCalendar();
ccalendar.removeObserver(unifinderObserver);
var ccalendar = getCompositeCalendar();
ccalendar.removeObserver(unifinderObserver);
var viewDeck = getViewDeck();
if (viewDeck) {
viewDeck.removeEventListener("dayselect", unifinderDaySelect, false);
viewDeck.removeEventListener("itemselect", unifinderItemSelect, true);
}
}
function unifinderOnDaySelect() {
/**
* Event listeners for dayselect and itemselect events
*/
function unifinderDaySelect() {
var filterList = document.getElementById("event-filter-menulist");
if (filterList.selectedItem.value == "current") {
refreshEventTree();
}
}
function unifinderItemSelect(aEvent) {
unifinderTreeView.setSelectedItems(aEvent.detail);
}
/**
* Helper function to display event datetimes in the unifinder
*/
@ -316,83 +253,6 @@ function formatUnifinderEventDateTime(aDatetime) {
return dateFormatter.formatDateTime(aDatetime.getInTimezone(kDefaultTimezone));
}
/**
* This is attached to the ondblclik attribute of the events shown in the
* unifinder
*/
function unifinderDoubleClickEvent(event) {
// we only care about button 0 (left click) events
if (event.button != 0) return;
// find event by id
var calendarEvent = getCalendarEventFromEvent(event);
if (calendarEvent != null) {
modifyEventWithDialog(getOccurrenceOrParent(calendarEvent));
} else {
createEventWithDialog();
}
}
/**
* Get the calendar from the given event
*/
function getCalendarEventFromEvent(event) {
var tree = document.getElementById("unifinder-search-results-tree");
var row = tree.treeBoxObject.getRowAt(event.clientX, event.clientY);
if (row != -1 && row < tree.view.rowCount) {
return tree.eventView.getCalendarEventAtRow(row);
} else {
return null;
}
}
/**
* This is attached to the onclik attribute of the events shown in the unifinder
*/
function unifinderOnSelect(event) {
if (event.target.view.selection.getRangeCount() == 0) {
return;
}
var arrayOfEvents = new Array();
gCalendarEventTreeClicked = true;
var calendarEvent;
// Get the selected events from the tree
var tree = document.getElementById("unifinder-search-results-tree");
var start = new Object();
var end = new Object();
var numRanges = tree.view.selection.getRangeCount();
for (var t = 0; t < numRanges; t++){
tree.view.selection.getRangeAt(t, start, end);
for (var v = start.value; v <= end.value; v++){
try {
calendarEvent = tree.eventView.getCalendarEventAtRow(v);
} catch (e) {
dump("Error getting Event from row: " + e + "\n");
return;
}
if (calendarEvent) {
arrayOfEvents.push(calendarEvent);
}
}
}
if (arrayOfEvents.length == 1) {
currentView().goToDay(arrayOfEvents[0].startDate);
}
// Pass in true, so we don't end up in a circular loop
currentView().setSelectedItems(arrayOfEvents.length, arrayOfEvents, true);
onSelectionChanged({detail: arrayOfEvents});
}
/**
* This is called from the unifinder when a key is pressed in the search field
*/
@ -421,30 +281,262 @@ function clearSearchTimer() {
}
/**
* This function returns the event table.
* Unifinder event handlers (click,select,etc)
*/
function changeEventFilter(event) {
refreshEventTree();
function unifinderDoubleClick(event) {
// We only care about button 0 (left click) events
if (event.button != 0) {
return;
}
// The following isn't exactly right. It should actually reload after the
// next event happens.
// find event by id
var calendarEvent = unifinderTreeView.getItemFromEvent(event);
// get the current time
var now = new Date();
if (calendarEvent != null) {
modifyEventWithDialog(getOccurrenceOrParent(calendarEvent));
} else {
createEventWithDialog();
}
}
var tomorrow = new Date(now.getFullYear(), now.getMonth(), (now.getDate() + 1));
function unifinderSelect(event) {
var tree = unifinderTreeView.treeElement;
if (!tree.view.selection || tree.view.selection.getRangeCount() == 0) {
return;
}
var milliSecsTillTomorrow = tomorrow.getTime() - now.getTime();
var selectedItems = [];
gCalendarEventTreeClicked = true;
setTimeout("refreshEventTree()", milliSecsTillTomorrow);
// Get the selected events from the tree
var start = {};
var end = {};
var numRanges = tree.view.selection.getRangeCount();
for (var t = 0; t < numRanges; t++) {
tree.view.selection.getRangeAt(t, start, end);
for (var v = start.value; v <= end.value; v++) {
try {
selectedItems.push(unifinderTreeView.getItemAt(v));
} catch (e) {
WARN("Error getting Event from row: " + e + "\n");
}
}
}
if (selectedItems.length == 1) {
// Go to the day of the selected item in the current view.
currentView().goToDay(selectedItems[0].startDate);
}
// Set up the selected items in the view. Pass in true, so we don't end
// up in a circular loop
currentView().setSelectedItems(selectedItems.length, selectedItems, true);
onSelectionChanged({detail: selectedItems});
}
function unifinderKeyPress(aEvent) {
const kKE = Components.interfaces.nsIDOMKeyEvent;
switch (aEvent.keyCode) {
case 13:
// Enter, edit the event
editSelectedEvents();
break;
case kKE.DOM_VK_BACK_SPACE:
case kKE.DOM_VK_DELETE:
deleteSelectedEvents();
break;
}
}
/**
* Redraw the categories unifinder tree
*/
* Tree controller for unifinder search results
*/
var unifinderTreeView = {
get rowCount() {
return gEventArray.length;
tree: null,
treeElement: null,
doingSelection: false,
/**
* Event functions
*/
eventArray: [],
eventIndexMap: {},
addItems: function uTV_addItems(aItemArray, aDontSort) {
this.eventArray = this.eventArray.concat(aItemArray);
this.tree.rowCountChanged(this.eventArray.length - aItemArray.length,
aItemArray.length);
if (!aDontSort) {
this.sortItems();
}
},
removeItems: function uTV_removeItems(aItemArray) {
for each (var item in aItemArray) {
var row = this.getItemRow(item);
this.eventArray = this.eventArray.splice(row, 1);
this.tree.rowCountChanged(row, -1);
}
},
clearItems: function uTV_clearItems() {
this.eventArray = [];
this.tree.invalidate();
},
setItems: function uTV_setItems(aItemArray, aDontSort) {
this.eventArray = aItemArray.splice(0);
if (aDontSort) {
this.tree.invalidate();
} else {
this.sortItems();
}
},
sortItems: function uTV_sortItems() {
// Get a current locale string collator for compareEvents
var localeService =
Components
.classes["@mozilla.org/intl/nslocaleservice;1"]
.getService(Components.interfaces.nsILocaleService);
this.localeCollator =
Components
.classes["@mozilla.org/intl/collation-factory;1"]
.getService(Components.interfaces.nsICollationFactory)
.CreateCollation(localeService.getApplicationLocale());
// cache sort keys, used by compareEvents
this.sortKeyByEvent_cache = new Object();
for (var i in this.eventArray) {
var sortEvent = this.eventArray[i];
this.sortKeyByEvent_cache_put(sortEvent, getEventSortKey(sortEvent));
}
this.sortStartedTime = new Date().getTime(); // for null/0 dates in sort
this.eventArray.sort(compareEvents);
// Set up eventIndexMap
this.eventIndexMap = {};
for (var i = 0 ; i < this.eventArray.length; i++) {
this.eventIndexMap[this.eventArray[i].hashId] = i;
}
this.sortKeyByEvent_cache = null;
// Setting the view again refreshes the tree
this.treeElement.view = unifinderTreeView;
},
getItemRow: function uTV_getItemRow(item) {
return this.eventIndexMap[item.hashId];
},
getItemAt: function uTV_getItemAt(aRow) {
return this.eventArray[aRow];
},
/**
* Get the calendar item from the given event
*/
getItemFromEvent: function uTV_getItemFromEvent(event) {
var row = this.tree.getRowAt(event.clientX, event.clientY);
if (row > -1) {
return this.getItemAt(row);
}
return null;
},
setSelectedItems: function uTV_setSelectedItems(aItemArray) {
if (this.doingSelection) {
return;
}
this.doingSelection = true;
// If no items were passed, get the selected items from the view.
aItemArray = aItemArray || currentView().getSelectedItems({});
/**
* The following is a brutal hack, caused by
* http://lxr.mozilla.org/mozilla1.0/source/layout/xul/base/src/tree/src/nsTreeSelection.cpp#555
* and described in bug 168211
* http://bugzilla.mozilla.org/show_bug.cgi?id=168211
* Do NOT remove anything in the next 3 lines, or the selection in the tree will not work.
*/
this.treeElement.onselect = null;
this.treeElement.removeEventListener("select", unifinderSelect, true);
this.tree.view.selection.selectEventsSuppressed = true;
this.tree.view.selection.clearSelection();
if (aItemArray && aItemArray.length == 1) {
// If only one item is selected, scroll to it
var rowToScrollTo = this.getItemRow(aItemArray[0]);
if (rowToScrollTo > -1) {
this.tree.ensureRowIsVisible(rowToScrollTo);
this.tree.view.selection.timedSelect(rowToScrollTo, 1);
}
} else if (aItemArray && aItemArray.length > 1) {
// If there is more than one item, just select them all.
for (var i in aItemArray) {
var row = this.getItemRow(aItemArray[i]);
this.tree.view.selection.rangedSelect(row, row, true);
}
}
// This needs to be in a setTimeout
setTimeout("unifinderTreeView.resetAllowSelection()", 1);
},
resetAllowSelection: function uTV_resetAllowSelection() {
/**
* Do not change anything in the following lines, they are needed as
* described in the selection observer above
*/
this.doingSelection = false;
this.tree.view.selection.selectEventsSuppressed = false;
this.treeElement.addEventListener("select", unifinderSelect, true);
},
/**
* Tree View Implementation
*/
get rowCount uTV_getRowCount() {
return this.eventArray.length;
},
/* event is a calendar event. value is sortKey, a string or number */
sortKeyByEvent_cache_put : function uTV_cache_put( calEvent, value ) {
var earlierValues = this.sortKeyByEvent_cache[calEvent.id];
if (earlierValues == null && value != null) {
// common entry is just the value
this.sortKeyByEvent_cache[calEvent.id] = value;
} else {
// null key or rare dup id: link event & value to earlier value(s)
// id may be duplicated if event is in more than one calendar file.
var entry = new Object();
entry.isSortKeyByEventCacheEntry = true;
entry.event = calEvent;
entry.value = value;
entry.rest = earlierValues;
this.sortKeyByEvent_cache[calEvent.id] = entry;
}
},
sortKeyByEvent_cache_get : function uTV_cache_get( calEvent ) {
var entry = this.sortKeyByEvent_cache[calEvent.id];
while (typeof(entry) == "object" &&
"isSortKeyByEventCacheEntry" in entry) {
if (entry.event === calEvent) //pointer identity
return entry.value;
entry = entry.rest;
}
return entry; // only or last entry is first value put
},
selectedColumn: null,
@ -484,72 +576,15 @@ var unifinderTreeView = {
col.element.setAttribute("sortActive", "true");
col.element.setAttribute("sortDirection", this.sortDirection);
this.sortCalendarEvents();
this.sortItems();
document.getElementById("unifinder-search-results-tree").view = this;
},
sortCalendarEvents : function uTV_sortCalendarEvents()
{
// get a current locale string collator for compareEvents
var localeService =
Components
.classes["@mozilla.org/intl/nslocaleservice;1"]
.getService(Components.interfaces.nsILocaleService);
this.localeCollator =
Components
.classes["@mozilla.org/intl/collation-factory;1"]
.getService(Components.interfaces.nsICollationFactory)
.CreateCollation(localeService.getApplicationLocale());
// cache sort keys, used by compareEvents
this.sortKeyByEvent_cache = new Object();
for (var i in gEventArray) {
var sortEvent = gEventArray[i];
this.sortKeyByEvent_cache_put(sortEvent, getEventSortKey(sortEvent));
}
this.sortStartedTime = new Date().getTime(); // for null/0 dates in sort
gEventArray.sort(compareEvents);
this.sortKeyByEvent_cache = null;
},
/* event is a calendar event. value is sortKey, a string or number */
sortKeyByEvent_cache_put : function uTV_cache_put( calEvent, value )
{
var earlierValues = this.sortKeyByEvent_cache[calEvent.id];
if (earlierValues == null && value != null) {
// common entry is just the value
this.sortKeyByEvent_cache[calEvent.id] = value;
} else {
// null key or rare dup id: link event & value to earlier value(s)
// id may be duplicated if event is in more than one calendar file.
var entry = new Object();
entry.isSortKeyByEventCacheEntry = true;
entry.event = calEvent;
entry.value = value;
entry.rest = earlierValues;
this.sortKeyByEvent_cache[calEvent.id] = entry;
}
},
sortKeyByEvent_cache_get : function uTV_cache_get( calEvent )
{
var entry = this.sortKeyByEvent_cache[calEvent.id];
while (typeof(entry) == "object" &&
"isSortKeyByEventCacheEntry" in entry) {
if (entry.event === calEvent) //pointer identity
return entry.value;
entry = entry.rest;
}
return entry; // only or last entry is first value put
},
setTree: function uTV_setTree(tree) { this.tree = tree; },
getCellText: function uTV_getCellText(row, column) {
calendarEvent = gEventArray[row];
calendarEvent = this.eventArray[row];
switch (column.id) {
case "unifinder-search-results-tree-col-title":
@ -614,11 +649,10 @@ function getEventSortKey(calEvent) {
}
}
function compareEvents( calEventA, calEventB )
{
var modifier = (unifinderTreeView.sortDirection == "descending"? -1 : 1);
switch(unifinderTreeView.selectedColumn) {
function compareEvents(calEventA, calEventB) {
var modifier = (unifinderTreeView.sortDirection == "descending" ? -1 : 1);
switch (unifinderTreeView.selectedColumn) {
case "unifinder-search-results-tree-col-startdate":
case "unifinder-search-results-tree-col-enddate":
var msA = unifinderTreeView.sortKeyByEvent_cache_get(calEventA);
@ -639,12 +673,12 @@ function compareEvents( calEventA, calEventB )
return -(strA.length - strB.length) * modifier;
}
var comparison =
unifinderTreeView.localeCollator.compareString(0, strA, strB);
unifinderTreeView.localeCollator.compareString(0, strA, strB);
return comparison * modifier;
default:
return 0;
}
}
}
function compareMSTime(a, b) {
@ -689,30 +723,6 @@ function dateToMilliseconds(date) {
return ms;
}
function calendarEventView(eventArray) {
this.eventArray = eventArray;
}
calendarEventView.prototype = {
eventArray: null,
getCalendarEventAtRow: function(i) {
return gEventArray[i];
},
getRowOfCalendarEvent: function(event) {
if (!event) {
return null;
}
for (var i in gEventArray) {
if (gEventArray[i].hashId == event.hashId) {
return i;
}
}
return null;
}
};
function refreshEventTree() {
if (isUnifinderHidden()) {
// If the unifinder is hidden, don't refresh the events to reduce needed
@ -816,79 +826,44 @@ function refreshEventTree() {
if (StartDate && EndDate) {
filter |= ccalendar.ITEM_FILTER_CLASS_OCCURRENCES;
}
LOG("GETITEMS FOR UNIFINDER " + STACK());
ccalendar.getItems(filter, 0, gStartDate, gEndDate, refreshListener);
}
function refreshEventTreeInternal(eventArray) {
var searchText = document.getElementById("unifinder-search-field").value;
var unifinderTree = document.getElementById("unifinder-search-results-tree");
searchText = searchText.toLowerCase();
// XXX match for strings with only whitespace. Skip those too
if (searchText.length) {
gEventArray = new Array();
var fieldsToSearch = ["DESCRIPTION", "LOCATION", "CATEGORIES", "URL"];
if (searchText.length && !searchText.match(/^\s*$/)) {
unifinderTreeView.clearItems();
const fieldsToSearch = ["SUMMARY", "DESCRIPTION", "LOCATION", "CATEGORIES", "URL"];
for (var j in eventArray) {
var event = eventArray[j];
if (event.title &&
event.title.toLowerCase().indexOf(searchText) != -1) {
gEventArray.push(event);
} else {
for (var k in fieldsToSearch) {
var val = event.getProperty(fieldsToSearch[k]);
if (val && val.toLowerCase().indexOf(searchText) != -1) {
gEventArray.push(event);
break;
}
var item = eventArray[j];
if (!fixAlldayDates(item)) {
continue;
}
for each (var field in fieldsToSearch) {
var val = event.getProperty(fieldsToSearch[field]);
if (val && val.toLowerCase().indexOf(searchText) != -1) {
unifinderTreeView.addItems([event], true);
break;
}
}
}
// Finally, sort the items since it was suppressed above
unifinderTreeView.sortItems();
} else {
gEventArray = eventArray;
unifinderTreeView.setItems(eventArray.filter(fixAlldayDates));
}
// Extra check to see if the events are in the daterange. Some providers
// are broken when looking at all-day events.
function dateFilter(event) {
// Using .compare on the views start and end, not on the events dates,
// because .compare uses the timezone of the datetime it is called on.
// The view's timezone is what is important here.
return ((!gEndDate || gEndDate.compare(event.startDate) >= 0) &&
(!gStartDate || gStartDate.compare(event.endDate) < 0));
}
gEventArray = gEventArray.filter(dateFilter);
var unifinderTree = document.getElementById("unifinder-search-results-tree");
var arrayOfTreeCols = unifinderTree.getElementsByTagName("treecol");
for (var i = 0; i < arrayOfTreeCols.length; i++) {
if (arrayOfTreeCols[i].getAttribute("sortActive") == "true") {
unifinderTreeView.selectedColumn = arrayOfTreeCols[i].getAttribute("id");
unifinderTreeView.sortDirection = arrayOfTreeCols[i].getAttribute("sortDirection");
unifinderTreeView.sortCalendarEvents();
break;
}
}
unifinderTree.view = unifinderTreeView;
unifinderTree.eventView = new calendarEventView(gEventArray);
// Select selected events in the tree.
selectSelectedEventsInTree(false);
}
function unifinderKeyPress(aEvent) {
const kKE = Components.interfaces.nsIDOMKeyEvent;
switch (aEvent.keyCode) {
case 13:
// Enter, edit the event
editSelectedEvents();
break;
case kKE.DOM_VK_BACK_SPACE:
case kKE.DOM_VK_DELETE:
deleteSelectedEvents();
break;
}
// Select selected events in the tree. Not passing the argument gets the
// items from the view.
unifinderTreeView.setSelectedItems();
}
function focusSearch() {

View File

@ -61,7 +61,7 @@
<hbox id="unifinder-searchBox" persist="collapsed">
<box align="center">
<menulist id="event-filter-menulist" value="next7Days" persist="value">
<menupopup id="event-filter-menupopup" oncommand="changeEventFilter( event );">
<menupopup id="event-filter-menupopup" oncommand="refreshEventTree()">
<menuitem id="event-filter-all"
label="&calendar.events.filter.all.label;"
value="all"/>
@ -96,7 +96,7 @@
<toolbarbutton id="unifinder-closer" class="unifinder-closebutton" command="calendar_show_unifinder_command"/>
</hbox>
<tree id="unifinder-search-results-tree" flex="1"
onselect="unifinderOnSelect( event ); onSelectionChanged()"
onselect="unifinderSelect( event ); onSelectionChanged()"
onkeypress="unifinderKeyPress(event)"
enableColumnDrag="true">
<treecols id="unifinder-search-results-tree-cols">
@ -142,7 +142,7 @@
<treechildren tooltip="eventTreeTooltip"
onkeypress="if (event.keyCode == 13) unifinderEditCommand();"
ondragover="return( false );"
ondblclick="unifinderDoubleClickEvent( event )"
ondblclick="unifinderDoubleClick(event)"
onfocus="focusFirstItemIfNoSelection( );"/>
</tree>
</vbox>

View File

@ -306,6 +306,10 @@ function refreshUIBits() {
if (TodayPane.showsYesterday()) {
TodayPane.setDay(now());
}
// update the unifinder
refreshEventTree();
// schedule our next update...
scheduleMidnightUpdate(refreshUIBits);
}

View File

@ -82,7 +82,6 @@ function calendarInit() {
currentView().goToDay(currentView().selectedDay);
// set up the unifinder
prepareCalendarUnifinder();
prepareCalendarToDoUnifinder();
scheduleMidnightUpdate(refreshUIBits);
@ -214,12 +213,10 @@ function calendarFinish()
var tabbox = document.getElementById("tablist");
tabbox.setAttribute("selectedIndex", tabbox.selectedIndex);
finishCalendarUnifinder();
unloadCalendarManager();
// Finish the offline manager
calendarOfflineManager.uninit();
// Finish the offline manager
calendarOfflineManager.uninit();
}
function closeCalendar()

View File

@ -26,6 +26,7 @@
* Mike Norton <xor@ivwnet.com>
* ArentJan Banck <ajbanck@planet.nl>
* Eric Belhaire <belhaire@ief.u-psud.fr>
* Philipp Kewisch <mozilla@kewis.ch>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -82,7 +83,7 @@ function onMouseOverItem( occurrenceBoxMouseEvent )
/** For all instances of an event, as displayed by unifinder. **/
function onMouseOverEventTree( toolTip, mouseEvent )
{
var item = getCalendarEventFromEvent( mouseEvent );
var item = unifinderTreeView.getItemFromEvent(mouseEvent);
if (isEvent(item)) {
var holderBox = getPreviewForEvent(item);
if (holderBox) {