diff --git a/browser/components/places/content/places.js b/browser/components/places/content/places.js index 11c60f676f9..be7801dea93 100755 --- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -225,24 +225,29 @@ var PlacesPage = { */ rangeSelected: function PP_rangeSelected() { var result = this._content.getResult(); - var queries = result.getQueries({ }); - + var queries = this.getCurrentQueries(); + var calendar = document.getElementById("historyCalendar"); var begin = calendar.beginrange.getTime(); var end = calendar.endrange.getTime(); - if (begin == end) { - const DAY_MSEC = 86400000; - end = begin + DAY_MSEC; - } + + // The calendar restuns values in terms of whole days at midnight, inclusive. + // The end time range therefor must be moved to the evening of the end + // include that day in the query. + const DAY_MSEC = 86400000; + end += DAY_MSEC; + var newQueries = []; for (var i = 0; i < queries.length; ++i) { var query = queries[i].clone(); + query.beginTimeReference = Ci.nsINavHistoryQuery.TIME_RELATIVE_EPOCH; query.beginTime = begin * 1000; + query.endTimeReference = Ci.nsINavHistoryQuery.TIME_RELATIVE_EPOCH; query.endTime = end * 1000; newQueries.push(query); } - this._content.load(newQueries, result.queryOptions); + this._content.load(newQueries, this.getCurrentOptions()); return true; }, @@ -333,48 +338,72 @@ var PlacesPage = { * current result. */ _updateCalendar: function PP__updateCalendar() { - // Make sure that by updating the calendar widget we don't fire selection - // events and cause the UI to infinitely reload. var calendar = document.getElementById("historyCalendar"); - calendar.suppressRangeEvents = true; var result = this._content.getResult(); if (result.root.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) result.root.QueryInterface(Ci.nsINavHistoryQueryResultNode); else if (result.root.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER) result.root.QueryInterface(Ci.nsINavHistoryFolderResultNode); - else + else { + calendar.selectNothing = true; return; - var queries = result.root.getQueries({ }); - if (!queries.length) - return; - - // Query values are OR'ed together, so just use the first. - // FIXME: if there is more than one query, we probably do NOT want to - // highlight the date range in the calendar. - var query = queries[0]; - - const NOW = new Date(); - var begin = Math.floor(query.beginTime / 1000); - var end = Math.floor(query.endTime / 1000); - if (query.beginTimeReference == Ci.nsINavHistoryQuery.TIME_RELATIVE_TODAY) { - if (query.beginTime == 0) { - var d = new Date(); - d.setFullYear(NOW.getFullYear(), NOW.getMonth(), NOW.getDate()); - d.setHours(0, 0, 0, 0); - begin += d.getTime(); - } - else - begin += NOW.getTime(); - end += NOW.getTime(); } - calendar.beginrange = new Date(begin); - calendar.endrange = new Date(end); - - // Allow user selection events once again. + var queries = this.getCurrentQueries(); + + // if there is more than one query, make sure that they all specify the + // same date range. If there isn't a unique date range, don't display + // anything. + if (queries.length < 1) { + calendar.selectNothing = true; + return; + } + var absBegin = queries[0].absoluteBeginTime; + var absEnd = queries[0].absoluteEndTime; + for (var i = 1; i < queries.length; i ++) { + if (queries[i].absoluteBeginTime != absBegin || + queries[i].absoluteEndTime != absEnd) { + calendar.selectNothing = true; + return; + } + } + + var query = queries[0]; + + // Make sure that by updating the calendar widget we don't fire selection + // events and cause the UI to infinitely reload. + calendar.suppressRangeEvents = true; + + // begin + var beginRange = null; + if (query.hasBeginTime) + beginRange = new Date(query.absoluteBeginTime / 1000); + + // end + var endRange = null; + if (query.hasEndTime) { + endRange = new Date(query.absoluteEndTime / 1000); + + // here, we have to do a little work. Normally a day query will start + // at midnight and end exactly 24 hours later. However, this spans two + // actual days, and will show up as such in the calendar. Therefore, if + // the end day is exactly midnight, we will bump it back a day. + if (endRange.getHours() == 0 && endRange.getMinutes() == 0 && + endRange.getSeconds() == 0 && endRange.getMilliseconds() == 0) { + // Here, we have to be careful to not set the end range to before the + // beginning. Somebody stupid might set them to be the same, and we + // don't want to suddenly make an invalid range. + if (! beginRange || + (beginRange && beginRange.getTime() != endRange.getTime())) + endRange.setTime(endRange.getTime() - 1); + } + } + calendar.setRange(beginRange, endRange, true); + + // Allow user selection events once again. calendar.suppressRangeEvents = false; }, - + /** * Update the Places UI when the content of the right tree changes. */ @@ -394,8 +423,27 @@ var PlacesPage = { document.getElementById("historyCalendar").setAttribute("hidden", isBookmarks); // Update the calendar with the current date range, if applicable. - if (!isBookmarks) + if (!isBookmarks) { this._updateCalendar(); + } + }, + + /** + * Returns the query array associated with the query currently loaded in + * the main places pane. + */ + getCurrentQueries: function PP_getCurrentQueries() { + var result = this._content.getResult(); + return result.root.QueryInterface(Ci.nsINavHistoryQueryResultNode).getQueries({}); + }, + + /** + * Returns the options associated with the query currently loaded in the + * main places pane. + */ + getCurrentOptions: function PP_getCurrentOptions() { + var result = this._content.getResult(); + return result.root.QueryInterface(Ci.nsINavHistoryQueryResultNode).queryOptions; }, }; @@ -868,16 +916,17 @@ var PlacesQueryBuilder = { // Set max results var result = PlacesPage._content.getResult(); + var options = PlacesPage.getCurrentOptions(); if (document.getElementById("advancedSearchHasMax").checked) { var max = parseInt(document.getElementById("advancedSearchMaxResults").value); if (isNaN(max)) max = 100; - result.queryOptions.maxResults = max; - dump("Max results = " + result.queryOptions.maxResults + "(" + max + ")\n"); + options.maxResults = max; + dump("Max results = " + options.maxResults + "(" + max + ")\n"); } // Make sure we're getting uri results, not visits - result.queryOptions.resultType = result.queryOptions.RESULT_TYPE_URI; + options.resultType = options.RESULT_TYPE_URI; - PlacesPage._content.load(queries, result.queryOptions); + PlacesPage._content.load(queries, options); }, }; diff --git a/browser/components/places/content/places.xml b/browser/components/places/content/places.xml index f2bb8461824..6d8ce7133a8 100755 --- a/browser/components/places/content/places.xml +++ b/browser/components/places/content/places.xml @@ -145,6 +145,7 @@ this._currentMonth = -1; this._currentYear = -1; this._cell0Date = null; // date for top left of calendar + this._selectNothing = false; this._selectBegin = null; this._selectEnd = null; @@ -203,6 +204,7 @@ return new Date(this._selectBegin); + this._selectNothing = false; this._selectBegin = val; this.updateSelection(this._selectBegin, this._selectEnd); this.fireRangeEvent(); @@ -216,12 +218,50 @@ return new Date(this._selectEnd); + this._selectNothing = false; this._selectEnd = val; this.updateSelection(this._selectBegin, this._selectEnd); this.fireRangeEvent(); + + + + + + = this._numCells) { + // reselect month for end range + this.visibleMonth = end; + } + } + this._selectNothing = false; + this.updateSelection(begin, end); + this.fireRangeEvent(); + ]]> + + + + + + return this._selectNothing; + + + this._selectNothing = val; + + + @@ -241,6 +281,7 @@ var date = this.cellToDate(event.target.getAttribute("anonid")); if (! date) return; + this._selectNothing = false; this._dragging = true; this._mouseDownOn = date; this.updateSelection(date, date); @@ -324,18 +365,23 @@ = beginIndex && i <= endIndex); if (sel != this._selected[i]) { diff --git a/browser/components/places/content/tree.xml b/browser/components/places/content/tree.xml index cae1adc0214..91ffab2de5a 100644 --- a/browser/components/places/content/tree.xml +++ b/browser/components/places/content/tree.xml @@ -179,7 +179,7 @@ diff --git a/browser/components/places/public/nsINavHistoryService.idl b/browser/components/places/public/nsINavHistoryService.idl index 6dc89225d24..fc94b355e65 100644 --- a/browser/components/places/public/nsINavHistoryService.idl +++ b/browser/components/places/public/nsINavHistoryService.idl @@ -634,6 +634,9 @@ interface nsINavHistoryQuery : nsISupports * the time is not part of the query. This is the default, so an empty query * will match any time. The has* functions return whether the corresponding * time is considered. + * + * You can read absolute*Time to get the time value that the currently loaded + * reference points + offset resolve to. */ const PRUint32 TIME_RELATIVE_EPOCH = 0; const PRUint32 TIME_RELATIVE_TODAY = 1; @@ -642,10 +645,12 @@ interface nsINavHistoryQuery : nsISupports attribute PRTime beginTime; attribute PRUint32 beginTimeReference; readonly attribute boolean hasBeginTime; + readonly attribute PRTime absoluteBeginTime; attribute PRTime endTime; attribute PRUint32 endTimeReference; readonly attribute boolean hasEndTime; + readonly attribute PRTime absoluteEndTime; /** * Text search terms. diff --git a/browser/components/places/src/nsNavHistoryQuery.cpp b/browser/components/places/src/nsNavHistoryQuery.cpp index 5444c6d10b2..ea5e5fe5db1 100644 --- a/browser/components/places/src/nsNavHistoryQuery.cpp +++ b/browser/components/places/src/nsNavHistoryQuery.cpp @@ -730,6 +730,13 @@ NS_IMETHODIMP nsNavHistoryQuery::GetHasBeginTime(PRBool* _retval) return NS_OK; } +/* readonly attribute PRTime absoluteBeginTime; */ +NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteBeginTime(PRTime* _retval) +{ + *_retval = nsNavHistory::NormalizeTime(mBeginTimeReference, mBeginTime); + return NS_OK; +} + /* attribute PRTime endTime; */ NS_IMETHODIMP nsNavHistoryQuery::GetEndTime(PRTime *aEndTime) { @@ -763,6 +770,13 @@ NS_IMETHODIMP nsNavHistoryQuery::GetHasEndTime(PRBool* _retval) return NS_OK; } +/* readonly attribute PRTime absoluteEndTime; */ +NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteEndTime(PRTime* _retval) +{ + *_retval = nsNavHistory::NormalizeTime(mEndTimeReference, mEndTime); + return NS_OK; +} + /* attribute string searchTerms; */ NS_IMETHODIMP nsNavHistoryQuery::GetSearchTerms(nsAString& aSearchTerms) {