Bug 323492 r=bryner,beng Places history result node refactor, dynamic updates, performance improvements.

This commit is contained in:
brettw%gmail.com 2006-01-24 01:24:15 +00:00
parent 5c25684de4
commit a0f8231c69
22 changed files with 5593 additions and 2777 deletions

View File

@ -43,7 +43,7 @@ const Ci = Components.interfaces;
const Cc = Components.classes;
const Cr = Components.results;
const SELECTION_CONTAINS_URL = 0x01;
const SELECTION_CONTAINS_URI = 0x01;
const SELECTION_CONTAINS_CONTAINER = 0x02;
const SELECTION_IS_OPEN_CONTAINER = 0x04;
const SELECTION_IS_CLOSED_CONTAINER = 0x08;
@ -104,16 +104,15 @@ function InsertionPoint(folderId, index, orientation) {
* Initialization Configuration for a View
* @constructor
*/
function ViewConfig(dropTypes, dropOnTypes, filterOptions, firstDropIndex) {
function ViewConfig(dropTypes, dropOnTypes, excludeItems, expandQueries, firstDropIndex) {
this.dropTypes = dropTypes;
this.dropOnTypes = dropOnTypes;
this.filterOptions = filterOptions;
this.excludeItems = excludeItems;
this.expandQueries = expandQueries;
this.firstDropIndex = firstDropIndex;
}
ViewConfig.GENERIC_DROP_TYPES = [TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE,
TYPE_X_MOZ_URL];
ViewConfig.GENERIC_FILTER_OPTIONS = Ci.nsINavHistoryQuery.INCLUDE_ITEMS +
Ci.nsINavHistoryQuery.INCLUDE_QUERIES;
/**
* Manages grouping options for a particular view type.
@ -238,17 +237,22 @@ var PlacesController = {
* Generates a HistoryResult for the contents of a folder.
* @param folderId
* The folder to open
* @param filterOptions
* Options regarding the type of items to be returned. See
* documentation in nsINavHistoryQuery for the |itemTypes| property.
* @param excludeItems
* True to hide all items (individual bookmarks). This is used on
* the left places pane so you just get a folder hierarchy.
* @param expandQueries
* True to make query items expand as new containers. For managing,
* you want this to be false, for menus and such, you want this to
* be true.
* @returns A HistoryResult containing the contents of the folder.
*/
getFolderContents: function PC_getFolderContents(folderId, filterOptions) {
getFolderContents: function PC_getFolderContents(folderId, excludeItems, expandQueries) {
var query = this._hist.getNewQuery();
query.setFolders([folderId], 1);
query.itemTypes = filterOptions;
var options = this._hist.getNewQueryOptions();
options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1);
options.excludeItems = excludeItems;
options.expandQueries = expandQueries;
return this._hist.executeQuery(query, options);
},
@ -385,8 +389,7 @@ var PlacesController = {
* @returns true if the node is a Bookmark folder, false otherwise
*/
nodeIsFolder: function PC_nodeIsFolder(node) {
return (node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY &&
node.folderId > 0);
return (node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER);
},
/**
@ -395,10 +398,11 @@ var PlacesController = {
* A NavHistoryResultNode
* @returns true if the node is a URL item, false otherwise
*/
nodeIsURL: function PC_nodeIsURL(node) {
nodeIsURI: function PC_nodeIsURI(node) {
const NHRN = Ci.nsINavHistoryResultNode;
return node.type == NHRN.RESULT_TYPE_URL ||
node.type == NHRN.RESULT_TYPE_VISIT;
return node.type == NHRN.RESULT_TYPE_URI ||
node.type == NHRN.RESULT_TYPE_VISIT ||
node.type == NHRN.RESULT_TYPE_FULL_VISIT;
},
/**
@ -456,10 +460,10 @@ var PlacesController = {
// Paste
this._setEnabled("placesCmd_edit:paste", this._canPaste());
// Open
var hasSelectedURL = this._activeView.selectedURLNode != null;
this._setEnabled("placesCmd_open", hasSelectedURL);
this._setEnabled("placesCmd_open:window", hasSelectedURL);
this._setEnabled("placesCmd_open:tab", hasSelectedURL);
var hasSelectedURI = this._activeView.selectedURINode != null;
this._setEnabled("placesCmd_open", hasSelectedURI);
this._setEnabled("placesCmd_open:window", hasSelectedURI);
this._setEnabled("placesCmd_open:tab", hasSelectedURI);
// We can open multiple links in tabs if there is either:
// a) a single folder selected
@ -469,7 +473,7 @@ var PlacesController = {
this._setEnabled("placesCmd_open:tabs",
singleFolderSelected || !hasSingleSelection);
var viewIsFolder = this.nodeIsFolder(this._activeView.getResult());
var viewIsFolder = this.nodeIsFolder(this._activeView.getResult().root);
// Persistent Sort
this._setEnabled("placesCmd_sortby:name", viewIsFolder);
// New Folder
@ -499,19 +503,21 @@ var PlacesController = {
var metadata = { mixed: true };
var hasSingleSelection = this._activeView.hasSingleSelection;
if (this._activeView.selectedURLNode && hasSingleSelection)
if (this._activeView.selectedURINode && hasSingleSelection)
metadata["link"] = true;
var selectedNode = this._activeView.selectedNode;
if (this.nodeIsFolder(selectedNode) && hasSingleSelection)
metadata["folder"] = true;
if (this.nodeIsContainer(selectedNode) && hasSingleSelection)
metadata["container"] = true;
if (hasSingleSelection) {
var selectedNode = this._activeView.selectedNode;
if (this.nodeIsFolder(selectedNode))
metadata["folder"] = true;
if (this.nodeIsContainer(selectedNode))
metadata["container"] = true;
}
var foundNonLeaf = false;
var nodes = this._activeView.getSelectionNodes();
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
if (node.type != Ci.nsINavHistoryResultNode.RESULT_TYPE_URL)
if (node.type != Ci.nsINavHistoryResultNode.RESULT_TYPE_URI)
foundNonLeaf = true;
if (!node.readonly && node.folderType == "")
metadata["mutable"] = true;
@ -617,27 +623,30 @@ var PlacesController = {
* Loads the selected URL in a new tab.
*/
openLinkInNewTab: function PC_openLinkInNewTab() {
var node = this._activeView.selectedURLNode;
var node = this._activeView.selectedURINode;
if (node)
this._activeView.browserWindow.openNewTabWith(node.url, null, null);
this._activeView.browserWindow.openNewTabWith(
node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri, null, null);
},
/**
* Loads the selected URL in a new window.
*/
openLinkInNewWindow: function PC_openLinkInNewWindow() {
var node = this._activeView.selectedURLNode;
var node = this._activeView.selectedURINode;
if (node)
this._activeView.browserWindow.openNewWindowWith(node.url, null, null);
this._activeView.browserWindow.openNewWindowWith(
node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri, null, null);
},
/**
* Loads the selected URL in the current window, replacing the Places page.
*/
openLinkInCurrentWindow: function PC_openLinkInCurrentWindow() {
var node = this._activeView.selectedURLNode;
var node = this._activeView.selectedURINode;
if (node)
this._activeView.browserWindow.loadURI(node.url, null, null);
this._activeView.browserWindow.loadURI(
node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri, null, null);
},
/**
@ -652,16 +661,19 @@ var PlacesController = {
var cc = kids.childCount;
for (var i = 0; i < cc; ++i) {
var node = kids.getChild(i);
if (this.nodeIsURL(node))
this._activeView.browserWindow.openNewTabWith(node.url,
null, null);
if (this.nodeIsURI(node))
this._activeView.browserWindow.openNewTabWith(
node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri,
null, null);
}
}
else {
var nodes = this._activeView.getSelectionNodes();
for (var i = 0; i < nodes.length; ++i) {
if (this.nodeIsURL(nodes[i]))
this._activeView.browserWindow.openNewTabWith(nodes[i].url, null, null);
if (this.nodeIsURI(nodes[i]))
this._activeView.browserWindow.openNewTabWith(
nodes[i].QueryInterface(Ci.nsINavHistoryURIResultNode).uri,
null, null);
}
}
},
@ -683,8 +695,9 @@ var PlacesController = {
if (!this._groupableView)
return;
var result = this._groupableView.getResult();
var queries = result.getQueries({ });
var newOptions = result.queryOptions.clone();
var root = result.root.QueryInterface(Ci.nsINavHistoryQueryResultNode);
var queries = root.getQueries({ });
var newOptions = root.queryOptions.clone();
// Update the grouping mode only after persisting, so that the URI is not
// changed.
@ -753,36 +766,41 @@ var PlacesController = {
remove: function PC_remove(txnName) {
var nodes = this._activeView.getSelectionNodes();
this._activeView.saveSelection();
if (this._activeView.isBookmarks) {
// delete bookmarks
var txns = [];
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
var index = this.getIndexOfNode(node);
if (this.nodeIsFolder(node)) {
txns.push(new PlacesRemoveFolderTransaction(node.folderId,
node.parent.folderId,
index));
}
else {
txns.push(new PlacesRemoveItemTransaction(this._uri(node.url),
node.parent.folderId,
// delete bookmarks
var txns = [];
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
var index = this.getIndexOfNode(node);
if (this.nodeIsFolder(node)) {
txns.push(new PlacesRemoveFolderTransaction(node.folderId,
node.parent.folderId,
index));
}
else if (this.nodeIsFolder(node.parent)) {
// this item is in a bookmark folder
txns.push(new PlacesRemoveItemTransaction(this._uri(node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri),
node.parent.folderId,
index));
}
else {
// other containers are history queries, just delete from history
// history deletes are not undoable.
var hist = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsIBrowserHistory);
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
if (this.nodeIsHost(node)) {
hist.removePagesFromHost(node.title, true);
} else if (this.nodeIsURI(node)) {
hist.removePage(this._uri(node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri));
}
}
}
var txn = new PlacesAggregateTransaction(txnName || "RemoveItems", txns);
this._hist.transactionManager.doTransaction(txn);
} else {
// delete history items: these are unfortunately not undoable.
var hist = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsIBrowserHistory);
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
if (this.nodeIsHost(node)) {
hist.removePagesFromHost(node.title, true);
} else {
hist.removePage(this._uri(node.url));
}
if (txns.length > 0) {
var txn = new PlacesAggregateTransaction(txnName || "RemoveItems", txns);
this._hist.transactionManager.doTransaction(txn);
}
}
this._activeView.restoreSelection();
@ -817,14 +835,14 @@ var PlacesController = {
switch (type) {
case TYPE_X_MOZ_PLACE_CONTAINER:
case TYPE_X_MOZ_PLACE:
return node.folderId + "\n" + node.url + "\n" + node.parent.folderId + "\n" + this.getIndexOfNode(node);
return node.folderId + "\n" + node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri + "\n" + node.parent.folderId + "\n" + this.getIndexOfNode(node);
case TYPE_X_MOZ_URL:
return node.url + "\n" + node.title;
return node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri + "\n" + node.title;
case TYPE_HTML:
return "<A HREF=\"" + node.url + "\">" + node.title + "</A>";
return "<A HREF=\"" + node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri + "\">" + node.title + "</A>";
}
// case TYPE_UNICODE:
return node.url;
return node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri;
},
/**
@ -904,15 +922,14 @@ var PlacesController = {
transactions.push(createTxn);
// Get the folder's children
var kids = self.getFolderContents(folderId,
ViewConfig.GENERIC_FILTER_OPTIONS);
var kids = self.getFolderContents(folderId, false, false);
var cc = kids.childCount;
for (var i = 0; i < cc; ++i) {
var node = kids.getChild(i);
if (self.nodeIsFolder(node))
createTransactions(node.folderId, folderId, i);
else {
var uri = self._uri(node.url);
else if (this.nodeIsURI(node)) {
var uri = self._uri(node.QueryInterface(Ci.nsINavHistoryURIResultNode).uri);
transactions.push(self._getItemCopyTransaction(uri, container,
index));
}
@ -1145,7 +1162,7 @@ var PlacesControllerDragHelper = {
*/
canDrop: function PCDH_canDrop(view, orientation) {
var result = view.getResult();
if (result.readOnly || !PlacesController.nodeIsFolder(result))
if (result.readOnly || !PlacesController.nodeIsFolder(result.root))
return false;
var session = this._getSession();
@ -1490,7 +1507,7 @@ PlacesEditItemTransaction.prototype = {
selection flags
flags:
SELECTION_CONTAINS_URL
SELECTION_CONTAINS_URI
SELECTION_CONTAINS_CONTAINER_OPEN
SELECTION_CONTAINS_CONTAINER_CLOSED
SELECTION_CONTAINS_CHANGEABLE

View File

@ -37,14 +37,6 @@
// options.setExpandPlaces(); ?
this._result = this._places.executeQuery(query, options);
// If this is a container, notify the service.
if (PlacesController.nodeIsContainer(this._result)) {
var serv = Cc[this._result.folderType]
.getService(Ci.nsIBookmarksContainer);
if (serv.onContainerOpening(this._result.folderId))
this._result = this._places.executeQuery(query, options);
}
this._rebuild();
if (this.popupShowingCallback)
this.popupShowingCallback();
@ -92,15 +84,15 @@
<body><![CDATA[
this._cleanMenu();
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var cc = this._result.childCount;
var cc = this._result.root.childCount;
if (cc > 0) {
for (var i = 0; i < cc; ++i) {
var child = this._result.getChild(i);
var child = this._result.root.getChild(i);
var element = null;
if (PlacesController.nodeIsURL(child)) {
if (PlacesController.nodeIsURI(child)) {
element = document.createElementNS(XULNS, "menuitem");
element.setAttribute("label", child.title);
element.setAttribute("url", child.url);
element.setAttribute("url", child.QueryInterface(nsINavHistoryURIResultNode).uri);
element.setAttribute("statustext", child.url);
element.setAttribute("image", child.icon.spec);
element.className = "menuitem-iconic bookmark-item";
@ -183,10 +175,10 @@
]]></getter>
</property>
<property name="selectedURLNode">
<property name="selectedURINode">
<getter><![CDATA[
var node = this.selectedNode;
return node && PlacesController.nodeIsURL(node) ? node : null;
return node && PlacesController.nodeIsURI(node) ? node : null;
]]></getter>
</property>
@ -200,7 +192,7 @@
if(PlacesController.nodeIsFolder(this.selectedNode))
// If there is a folder selected, the insertion point is the
// end of the folder.
folderId = this.selectedNode.folderId;
folderId = this.selectedNode.QueryInterface(Ci.nsINavHistoryFolderResultNode).folderId;
else
// If there is another type of node selected, the insertion point
// is after that node.
@ -249,7 +241,7 @@
onItemChanged: function TB_O_onItemChanged(bookmark, property, value) {
//this._self.init();
},
onItemVisited: function TB_0_onItemVisited(bookmark, time) {
onItemVisited: function TB_0_onItemVisited(bookmark, visitId, time) {
//this._self.init();
},
onItemReplaced: function TB_0_onItemReplaced(filder, item, newItem) {

View File

@ -175,12 +175,11 @@ var PlacesPage = {
this._places.init(new ViewConfig([TYPE_X_MOZ_PLACE_CONTAINER],
ViewConfig.GENERIC_DROP_TYPES,
Ci.nsINavHistoryQuery.INCLUDE_QUERIES,
ViewConfig.GENERIC_FILTER_OPTIONS, 3));
true, false, 3));
this._content.init(new ViewConfig(ViewConfig.GENERIC_DROP_TYPES,
ViewConfig.GENERIC_DROP_TYPES,
ViewConfig.GENERIC_FILTER_OPTIONS, 0));
false, false, 0));
PlacesController.groupableView = this._content;
var GroupingSerializer = {
@ -309,21 +308,24 @@ var PlacesPage = {
var node = this._places.selectedNode;
if (!node || this._places.suppressSelection)
return;
if (node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER)
node.QueryInterface(Ci.nsINavHistoryFolderResultNode);
else if (node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY)
node.QueryInterface(Ci.nsINavHistoryQueryResultNode);
else
return; // should not get here
var queries = node.getQueries({});
var newQueries = [];
for (var i = 0; i < queries.length; ++i) {
var query = queries[i].clone();
query.itemTypes |= this._content.filterOptions;
newQueries.push(query);
}
var newOptions = node.queryOptions.clone();
var groupings = PlacesController.groupers.generic.value;
var isBookmark = PlacesController.nodeIsFolder(node);
if (isBookmark)
groupings = PlacesController.groupers.bookmark.value;
newOptions.setGroupingMode(groupings, groupings.length);
this._content.load(newQueries, newOptions);
this._setHeader("showing", node.title);
@ -340,11 +342,19 @@ var PlacesPage = {
calendar.suppressRangeEvents = true;
var result = this._content.getResult();
var queries = result.getQueries({ });
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
return;
var queries = result.root.getQueries({ });
if (!queries.length)
return;
// Query values are OR'ed together, so just use the first.
// 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();
@ -868,8 +878,8 @@ var PlacesQueryBuilder = {
result.queryOptions.maxResults = max;
dump("Max results = " + result.queryOptions.maxResults + "(" + max + ")\n");
}
// Make sure we're getting url results, not visits
result.queryOptions.resultType = result.queryOptions.RESULT_TYPE_URL;
// Make sure we're getting uri results, not visits
result.queryOptions.resultType = result.queryOptions.RESULT_TYPE_URI;
PlacesPage._content.load(queries, result.queryOptions);
},

View File

@ -35,16 +35,6 @@
var options = this._places.getNewQueryOptions();
options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1);
this._result = this._places.executeQuery(query, options);
// Check if the new query needs a show event.
if (PlacesController.nodeIsContainer(this._result)) {
var serv = Cc[this._result.folderType]
.getService(Ci.nsIBookmarksContainer);
if (serv.onContainerOpening(this._result.folderId))
this._result = this._places.executeQueries(queries, queries.length,
options);
}
this._rebuild();
]]></body>
</method>
@ -66,13 +56,14 @@
while (this.hasChildNodes())
this.removeChild(this.firstChild);
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var cc = this._result.childCount;
var cc = this._result.root.childCount;
for (var i = 0; i < cc; ++i) {
var child = this._result.getChild(i);
var child = this._result.root.getChild(i);
var button = document.createElementNS(XULNS, "toolbarbutton");
button.setAttribute("label", child.title);
if (PlacesController.nodeIsURL(child)) {
button.setAttribute("url", child.url);
if (PlacesController.nodeIsURI(child)) {
child = child.QueryInterface(Ci.nsINavHistoryURIResultNode);
button.setAttribute("url", child.uri);
button.setAttribute("image", child.icon.spec);
} else if (PlacesController.nodeIsFolder(child)) {
button.setAttribute("type", "menu");
@ -106,7 +97,7 @@
// This is set here and not in the XBL constructor for the menu because
// it doesn't get initialized properly in the constructor.
popup.setAttribute("context", "placesContext");
popup.folderId = this._result.folderId;
popup.folderId = this._result.root.QueryInterface(Ci.nsINavHistoryFolderResultNode).folderId;
var t = this;
popup.popupShowingCallback = function() {t.chevronPopupShowing();};
this._chevron.appendChild(popup);
@ -170,24 +161,8 @@
<parameter name="queries"/>
<parameter name="options"/>
<body><![CDATA[
// Check if the old query needs a hidden event.
if (PlacesController.nodeIsContainer(this._result)) {
var serv = Cc[this._result.folderType]
.getService(Ci.nsIBookmarksContainer);
serv.onContainerClosed(this._result.folderId);
}
this._result = this._places.executeQueries(queries, queries.length,
options);
// Check if the new query needs a show event.
if (PlacesController.nodeIsContainer(this._result)) {
var serv = Cc[this._result.folderType]
.getService(Ci.nsIBookmarksContainer);
if (serv.onContainerOpening(this._result.folderId))
this._result = this._places.executeQueries(queries, queries.length,
options);
}
this._rebuild();
]]></body>
</method>
@ -228,10 +203,10 @@
]]></getter>
</property>
<property name="selectedURLNode">
<property name="selectedURINode">
<getter><![CDATA[
var node = this.selectedNode;
return node && PlacesController.nodeIsURL(node) ? node : null;
return node && PlacesController.nodeIsURI(node) ? node : null;
]]></getter>
</property>
@ -239,7 +214,7 @@
<getter><![CDATA[
// By default, the insertion point is at the top level, at the end.
var index = -1;
var folderId = this._result.folderId;
var folderId = this._result.root.QueryInterface(nsINavHistoryFolderResultNode).folderId;
if (this.hasSelection) {
if(PlacesController.nodeIsFolder(this.selectedNode))
@ -298,7 +273,7 @@
if (!this._numBatches)
this._self.init();
},
onItemVisited: function TB_0_onItemVisited(bookmark, time) {
onItemVisited: function TB_0_onItemVisited(bookmark, visitId, time) {
//this._self.init();
},
onItemReplaced: function TB_0_onItemReplaced(filder, item, newItem) {

View File

@ -30,7 +30,7 @@
<body><![CDATA[
this.supportedDropTypes = viewConfig.dropTypes;
this.supportedDropOnTypes = viewConfig.dropOnTypes;
this.filterOptions = viewConfig.filterOptions;
this.excludeItems = viewConfig.excludeItems;
this.firstDropIndex = viewConfig.firstDropIndex;
]]></body>
</method>
@ -150,11 +150,11 @@
<body><![CDATA[
var query = this._places.getNewQuery();
query.setFolders([folderId], 1);
query.itemTypes = this.filterOptions;
var options = this._places.getNewQueryOptions();
options.setGroupingMode([Ci.nsINavHistoryQueryOptions.GROUP_BY_FOLDER], 1);
// options.setExpandPlaces(); ???
options.excludeItems = this.excludeItems;
options.expandQueries = false;
var result = this._places.executeQuery(query, options);
result.QueryInterface(Ci.nsITreeView);
this.view = result;
@ -166,6 +166,9 @@
<parameter name="queries"/>
<parameter name="options"/>
<body><![CDATA[
// override with our local options
options.excludeItems = this.excludeItems;
options.expandQueries = false;
var result = this._places.executeQueries(queries, queries.length,
options);
result.QueryInterface(Ci.nsITreeView);
@ -236,7 +239,7 @@
</property>
<!-- AVI Method -->
<property name="selectedURLNode">
<property name="selectedURINode">
<getter><![CDATA[
var view = this.view;
var selection = view.selection;
@ -245,12 +248,12 @@
return null;
var min = { }, max = { };
selection.getRangeAt(0, min, max);
// Cannot load containers
if (view.isContainer(min.value) || view.isSeparator(min.value))
return null;
return this.getResult().nodeForTreeIndex(min.value);
// only URI nodes should be returned
var node = this.getResult().nodeForTreeIndex(min.value);
if (PlacesController.nodeIsURI(node))
return node.QueryInterface(Ci.nsINavHistoryURIResultNode);
return null;
]]></getter>
</property>
@ -316,7 +319,7 @@
<field name="supportedDropOnTypes">null</field>
<!-- AVI Method -->
<field name="filterOptions">null</field>
<field name="excludeQueries">null</field>
<!-- AVI Method -->
<field name="dropOnFilterOptions">null</field>
@ -372,17 +375,17 @@
<method name="_getInsertionNode">
<parameter name="insertionPoint"/>
<parameter name="filterOptions"/>
<parameter name="excludeItems"/>
<body><![CDATA[
var result =
PlacesController.getFolderContents(insertionPoint.folderId,
filterOptions);
PlacesController.getFolderContents(insertionPoint.folderId,
excludeItems, false);
var index = insertionPoint.index;
if (insertionPoint.index == 0)
index = 0;
else if (insertionPoint.index == -1)
index = result.childCount - 1;
return index > -1 ? result.getChild(index) : null;
return index > -1 ? result.root.getChild(index) : null;
]]></body>
</method>
@ -391,12 +394,12 @@
<body><![CDATA[
const NHRVO = Ci.nsINavHistoryResultViewObserver;
// Insert index of insertion and number of rows to insert
var filterOptions = this.filterOptions;
var excludeItems = this.excludeItems;
// This is a bit of a hack. Assume any container you drop into is
// itself showing all item types, not just folders or items.
if (insertionPoint.orientation == NHRVO.DROP_ON)
filterOptions = ViewConfig.GENERIC_FILTER_OPTIONS;
var node = this._getInsertionNode(insertionPoint, filterOptions);
excludeItems = false;
var node = this._getInsertionNode(insertionPoint, excludeItems);
// This is the insertion index of the pivot.
return this.getResult().treeIndexForNode(node);
]]></body>
@ -485,23 +488,7 @@
visibleInsertCount);
},
onToggleOpenState: function VO_onToggleOpenState(index) {
// Alert containers about the toggle
var result = this._self.getResult();
var node = result.nodeForTreeIndex(index);
if (PlacesController.nodeIsContainer(node)) {
var serv = Cc[node.folderType].getService(Ci.nsIBookmarksContainer);
// This notification happens before the container is actually
// opened or closed, so the open state is the opposite of what
// we're notifying.
if (this._self.view.isContainerOpen(index)) {
serv.onContainerClosed(node.folderId);
} else {
if (serv.onContainerOpening(node.folderId))
this._self.loadFolder(node.folderId);
}
}
},
onToggleOpenState: function VO_onToggleOpenState(index) { },
onSelectionChanged: function VO_onSelectionChanged() { },
onCycleHeader: function VO_onCycleHeader(column) { },
onCycleCell: function VO_onCycleCell(row, column) { },

View File

@ -14,9 +14,10 @@ browser.jar:
classic.jar:
skin/classic/browser/places/places.css (skin-win/places.css)
skin/classic/browser/places/icons.png (skin-win/icons.png)
skin/classic/browser/places/default_favicon.png (skin-win/default_favicon.png)
skin/classic/browser/places/query.png (skin-win/query.png)
skin/classic/browser/places/bookmarks_menu.png (skin-win/bookmarks_menu.png)
skin/classic/browser/places/bookmarks_toolbar.png (skin-win/bookmarks_toolbar.png)
en-US.jar:
locale/browser/places/places.dtd (locale/places.dtd)

View File

@ -49,9 +49,9 @@ interface nsIFaviconService : nsISupports
* You needn't have specified any data at this point. An entry linking the
* favicon with the page will be create with no data. You can populate it
* later with SetFaviconData. However, any favicons not associated with a
* visited web page or bookmark will be expired when history cleanup is done
* (typically at app shutdown, but also possibly if the user clears their
* cache or history).
* visited web page, a bookmark, or a "place:" URI will be expired when
* history cleanup is done * (typically at app shutdown, but also possibly
* if the user clears their * cache or history).
*
* This will send out history notifications if the new favicon has any data.
* This means that you should try to set data first if you have it, otherwise
@ -99,10 +99,10 @@ interface nsIFaviconService : nsISupports
*
* You can set the data even if you haven't called SetFaviconUrlForPage
* yet. It will be stored but will not be associated with any page.
* However, any favicons not associated with a visited web page or bookmark
* will be expired when history cleanup is done (typically at app shutdown,
* but also possibly if the user clears their cache or history). It is best
* to call this function first for notification purposes.
* However, any favicons not associated with a visited web page, bookmark,
* or "place:" URI will be expired when history cleanup is done (typically
* at app shutdown, but also possibly if the user clears their cache or
* history). It is best to call this function first for notification purposes.
*
* The expiration time is stored. This will be used if you call
* SetAndLoadFaviconForPage to see whether the data needs reloading.

View File

@ -39,7 +39,6 @@
#include "nsISupports.idl"
interface nsIURI;
interface nsINavHistoryResult;
/**
* Observer for bookmark changes.
@ -117,7 +116,7 @@ interface nsINavBookmarkObserver : nsISupports
* @see onItemChanged properth = "cleartime" for when all visit dates are
* deleted for the URI.
*/
void onItemVisited(in nsIURI bookmark, in PRTime time);
void onItemVisited(in nsIURI bookmark, in PRInt64 aVisitID, in PRTime time);
/**
* Notify this observer that a bookmark has been replaced.
@ -294,7 +293,12 @@ interface nsINavBookmarksService : nsISupports
AString getFolderTitle(in PRInt64 folder);
/**
* Get the place: url for a bookmark folder.
* Get the place: url for a bookmark folder. You can use this value to
* get/set the icon for a folder or to associate other data with it using
* the annotation service. Its important that you use this function instead
* of just serializing the query/options for a given folder because you
* may have different options or query parameters. This function will give
* the canonical value.
* @param folder The folder whose URI should be retrieved
* @returns The URI for the folder
*/
@ -316,8 +320,8 @@ interface nsINavBookmarksService : nsISupports
/**
* Returns the list of folder ids that contain the given URI.
*/
void getBookmarkCategories(in nsIURI uri, out PRUint32 count,
[array, retval, size_is(count)] out PRInt64 categories);
void getBookmarkFolders(in nsIURI uri, out PRUint32 count,
[array, retval, size_is(count)] out PRInt64 folders);
/**
* Returns the index of the given item in the given folder.

View File

@ -40,11 +40,13 @@
#include "nsIArray.idl"
#include "nsIURI.idl"
interface nsIFile;
interface nsINavHistoryContainerResultNode;
interface nsINavHistoryQuery;
interface nsINavHistoryQueryOptions;
interface nsITransactionManager;
interface nsITreeColumn;
interface nsIFile;
interface nsIWritablePropertyBag;
[scriptable, uuid(acae2b2d-5fcd-4419-b1bc-b7dc92a1836c)]
interface nsINavHistoryResultNode : nsISupports
@ -53,37 +55,201 @@ interface nsINavHistoryResultNode : nsISupports
* Indentifies the parent result node in the result set. This is null for
* top level nodes.
*/
readonly attribute nsINavHistoryResultNode parent;
readonly attribute nsINavHistoryContainerResultNode parent;
/**
* Identifies the type of this node.
*/
const PRUint32 RESULT_TYPE_URL = 0;
const PRUint32 RESULT_TYPE_URI = 0;
const PRUint32 RESULT_TYPE_VISIT = 1;
const PRUint32 RESULT_TYPE_HOST = 2;
const PRUint32 RESULT_TYPE_DAY = 3;
const PRUint32 RESULT_TYPE_QUERY = 4;
const PRUint32 RESULT_TYPE_FULL_VISIT = 2;
const PRUint32 RESULT_TYPE_HOST = 3;
const PRUint32 RESULT_TYPE_DAY = 4;
const PRUint32 RESULT_TYPE_QUERY = 5;
const PRUint32 RESULT_TYPE_FOLDER = 6;
readonly attribute PRUint32 type;
/**
* URL of the web page in question. Empty for all other types, including
* Title of the web page, or of the node's grouping (day, host, folder, etc)
*/
readonly attribute AUTF8String title;
/**
* Total number of times the URI has ever been accessed. For hosts, this
* is the total of the children under it, NOT the total times the host has
* been accessed (this would require an additional query, so is not given
* by default when most of the time it is never needed).
*/
readonly attribute PRUint32 accessCount;
/**
* This is the time the user accessed the page.
*
* If this is a visit, it is the exact time that the page visit occurred.
*
* If this is a URI, it is the most recent time that the URI was visited.
* Even if you ask for all URIs for a given date range long ago, this might
* contain today's date if the URI was visited today.
*
* For hosts, or other node types with children, this is the most recent
* access time for any of the children.
*
* For days, this is midnight on the morning of the day in question in
* UTC time.
*/
readonly attribute PRTime time;
/**
* This URI can be used as an image source URI and will give you the favicon
* for the page. It is *not* the URI of the favicon, but rather something
* that will resolve to the actual image.
*
* In most cases, this is an annotation URI that will query the favicon
* service. If the entry has no favicon, this is the chrome URI of the
* default favicon. If the favicon originally lived in chrome, this will
* be the original chrome URI of the icon.
*/
readonly attribute nsIURI icon;
/**
* This is the number of levels between this node and the top of the
* hierarchy. The members of result.children have indentLevel = 0, their
* children have indentLevel = 1, etc.
*/
readonly attribute PRUint32 indentLevel;
/**
* You can use this to associate temporary information with the result node.
* This property bag is associated with the result node and is not persisted
* in any way.
*/
readonly attribute nsIWritablePropertyBag propertyBag;
};
/**
* This is a result node that includes a URI. Used for bookmark and URI
* results, as well as a base class for visit information.
*/
[scriptable, uuid(b62daf70-936a-41f8-a57e-6d2a6598bca6)]
interface nsINavHistoryURIResultNode : nsINavHistoryResultNode
{
/**
* URI of the web page in question. Empty for all other types, including
* hosts.
*/
readonly attribute AUTF8String url;
readonly attribute AUTF8String uri;
};
/**
* When you request RESULT_TYPE_VISIT from query options, you will get this
* interface for each item, which includes the session ID so that we can
* group items from the same session together.
*/
[scriptable, uuid(8e2c5a86-b33d-4fa6-944b-559af7e95fcd)]
interface nsINavHistoryVisitResultNode : nsINavHistoryURIResultNode
{
/**
* This indicates the session ID of the * visit. This is used for session
* grouping when a tree view is sorted by date.
*/
readonly attribute PRInt64 sessionId;
};
/**
* This structure will be returned when you request RESULT_TYPE_FULL_VISIT in
* the query options. This includes uncommonly used information about each
* visit.
*/
[scriptable, uuid(c49fd9d5-56e2-43eb-932c-f933f28cba85)]
interface nsINavHistoryFullVisitResultNode : nsINavHistoryVisitResultNode
{
/**
* This indicates the visit ID of the visit.
*/
readonly attribute PRInt64 visitId;
/**
* ID of the folder corresponding to this node.
* Only valid for RESULT_TYPE_QUERY nodes where exactly one folder
* has been specified in the query. 0 in all other cases.
* This indicates the referring visit ID of the visit. The referrer should
* have the same sessionId.
*/
readonly attribute PRInt64 folderId;
readonly attribute PRInt64 referringVisitId;
/**
* Type of the folder corresponding to this node.
* Only valid for RESULT_TYPE_QUERY nodes where exactly one folder
* has been specified in the query. 0 in all other cases.
* Indicates the transition type of the visit.
* One of nsINavHistoryService.TRANSITION_*
*/
readonly attribute AString folderType;
readonly attribute PRInt32 transitionType;
};
/**
* Base class for container results. This includes all types of groupings.
* Bookmark folders and places queries will be QueryResultNodes which extends
* these items.
*/
[scriptable, uuid(155757ea-482a-462e-9b14-70707d65afe3)]
interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode
{
/**
* Set this to allow descent into the container. When closed, attempting
* to call getChildren or childCount will result in an error. You should
* set this to false when you are done reading.
*
* For HOST and DAY groupings, doing this is free since the children have
* been precomputed. For queries and bookmark folders, being open means they
* will keep themselves up-to-date by listening for updates and re-querying
* as needed.
*/
attribute boolean containerOpen;
/**
* This indicates whether this node "may" have children, and can be used
* when the container is open or closed. When the container is closed, it
* will give you an exact answer if the node can easily be populated (for
* example, a bookmark folder). If not (for example, a complex history query),
* it will return true. When the container is open, it will always be
* accurate. It is intended to be used to see if we should draw the "+" next
* to a tree item.
*/
readonly attribute boolean hasChildren;
/**
* This gives you the children of the nodes. It is preferrable to use this
* interface over the array one, since it avoids creating an nsIArray object
* and the interface is already the correct type.
*/
readonly attribute PRUint32 childCount;
nsINavHistoryResultNode getChild(in PRUint32 index);
/**
* Returns false if this node's list of children can be modified
* (adding or removing children, or reordering children), or true if
* the UI should not allow the list of children to be modified.
* This is false for bookmark folder nodes unless setFolderReadOnly() has
* been called to override it, and true for non-folder nodes.
*/
readonly attribute boolean childrenReadOnly;
};
/**
* Used for places queries and as a base for bookmark folders.
*
* Note that if you request places to *not* be expanded in the options that
* generated this node, this item will report it has no children and never try
* to populate itself.
*/
[scriptable, uuid(dcd6a2b7-3d50-4c78-b1cb-2f0f18ac5864)]
interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode
{
/**
* A "place:" URI that encodes the query and options.
*/
readonly attribute nsIURI queryURI;
/**
* Get the queries which build this node's children.
@ -97,72 +263,23 @@ interface nsINavHistoryResultNode : nsISupports
* Only valid for RESULT_TYPE_QUERY nodes.
*/
readonly attribute nsINavHistoryQueryOptions queryOptions;
};
/**
* Title of the web page, or of the node's grouping (day, host, folder, etc)
*/
readonly attribute AString title;
/**
* Represents a bookmark folder (type == RESULT_TYPE_FOLDER). It derives from a
* query result because it can provide a query that will result in the
* contents.
*/
[scriptable, uuid(f3160bfe-ebb3-453b-b25e-19d0b9c425b1)]
interface nsINavHistoryFolderResultNode : nsINavHistoryQueryResultNode
{
/**
* Total number of times the URL has ever been accessed. For hosts, this
* is the total of the children under it, NOT the total times the host has
* been accessed (this would require an additional query, so is not given
* by default when most of the time it is never needed).
* ID of the folder corresponding to this node.
* Only valid for RESULT_TYPE_QUERY nodes where exactly one folder
* has been specified in the query. 0 in all other cases.
*/
readonly attribute PRInt32 accessCount;
/**
* This is the time the user accessed the page.
*
* If this is a visit, it is the exact time that the page visit occurred.
*
* If this is a URL, it is the most recent time that the URL was visited.
* Even if you ask for all URLs for a given date range long ago, this might
* contain today's date if the URL was visited today.
*
* For hosts, or other node types with children, this is the most recent
* access time for any of the children.
*
* For days, this is midnight on the morning of the day in question in
* UTC time.
*/
readonly attribute PRTime time;
/**
* This URI can be used as an image source URL and will give you the favicon
* for the page. It is *not* the URL of the favicon, but rather something
* that will resolve to the actual image.
*
* In most cases, this is an annotation URI that will query the favicon
* service. If the entry has no favicon, this is the chrome URL of the
* default favicon. If the favicon originally lived in chrome, this will
* be the original chrome URI of the icon.
*/
readonly attribute nsIURI icon;
/**
* This is the number of levels between this node and the top of the
* hierarchy. The members of result.children have indentLevel = 0, their
* children have indentLevel = 1, etc.
*/
readonly attribute PRInt32 indentLevel;
/**
* This gives you the children of the nodes. It is preferrable to use this
* interface over the array one, since it avoids creating an nsIArray object
* and the interface is already the correct type.
*/
readonly attribute PRInt32 childCount;
nsINavHistoryResultNode getChild(in PRInt32 index);
/**
* Returns false if this node's list of children can be modified
* (adding or removing children, or reordering children), or true if
* the UI should not allow the list of children to be modified.
* This is false for bookmark folder nodes unless setFolderReadOnly() has
* been called to override it, and true for non-folder nodes.
*/
readonly attribute boolean childrenReadOnly;
readonly attribute PRInt64 folderId;
};
@ -235,18 +352,19 @@ interface nsINavHistoryResultViewObserver : nsISupports
/**
* The result of a history/bookmark query.
*
* This class is also a result "node". Use those interfaces to access the
* toplevel children of this result.
* Use the "root" element to access the children of this query.
*/
[scriptable, uuid(25b45a94-3323-4c7b-910a-315f2c59bfb4)]
interface nsINavHistoryResult : nsINavHistoryResultNode
interface nsINavHistoryResult : nsISupports
{
/**
* Sorts all nodes recursively by the given parameter, one of
* nsINavHistory.SORT_BY_*
* nsINavHistory.SORT_BY_* This will update the corresponding options for
* this result, so that re-using the current options/queries will always give
* you the current view.
*/
void recursiveSort(in PRUint32 aSortingMode);
void sortAll(in PRUint32 aSortingMode);
/**
* Controls whether duplicate adjacent elements are collapsed into a single
@ -254,18 +372,12 @@ interface nsINavHistoryResult : nsINavHistoryResultNode
* things when you have selected to get visits. When you sort by date, the
* multiple entries will then appear because they will be separated (unless
* you clicked reload a bunch of times in a row). If you know you'll only
* ever want one entry per site, you should ask for URLs back instead of
* ever want one entry per site, you should ask for URIs back instead of
* visits so it will be more efficient.
* Default = true
*/
attribute boolean collapseDuplicates;
/**
* Call these functions to expand or collapse all elements in the tree.
*/
void expandAll();
void collapseAll();
/**
* This allows you to get at the real node for a given row index in the tree.
*/
@ -293,6 +405,15 @@ interface nsINavHistoryResult : nsINavHistoryResultNode
* Remove a tree builder observer.
*/
void removeObserver(in nsINavHistoryResultViewObserver observer);
/**
* This is the root of the results. It will either be a
* nsINavHistoryFolderResultNode (if the query is for bookmarks matching a
* single folder) or just a nsINavHistoryQueryResultNode (for everything
* else). The root node is open by default. Remember that you need to open
* all other containers for their contents to be valid.
*/
readonly attribute nsINavHistoryQueryResultNode root;
};
/**
@ -435,7 +556,8 @@ interface nsINavHistoryQuery : nsISupports
readonly attribute boolean hasSearchTerms;
/**
* When set, returns only bookmarked items, when unset, returns anything.
* When set, returns only bookmarked items, when unset, returns anything. Setting this
* is equivalent to listing all bookmark folders in the 'folders' parameter.
*/
attribute boolean onlyBookmarked;
@ -483,19 +605,6 @@ interface nsINavHistoryQuery : nsISupports
void setFolders([const,array, size_is(folderCount)] in PRInt64 folders,
in PRUint32 folderCount);
/**
* Constants for itemTypes
*/
const PRUint32 INCLUDE_ITEMS = 1;
const PRUint32 INCLUDE_QUERIES = 2;
/**
* Filter the items returned. Takes a bitwise combination of INCLUDE_*
* constants. Note that folders are only returned when a parent folder
* is specified with setFolders().
*/
attribute PRUint32 itemTypes;
/**
* Creates a new query item with the same parameters of this one.
*/
@ -554,21 +663,31 @@ interface nsINavHistoryQueryOptions : nsISupports
const PRUint32 SORT_BY_TITLE_DESCENDING = 2;
const PRUint32 SORT_BY_DATE_ASCENDING = 3;
const PRUint32 SORT_BY_DATE_DESCENDING = 4;
const PRUint32 SORT_BY_URL_ASCENDING = 5;
const PRUint32 SORT_BY_URL_DESCENDING = 6;
const PRUint32 SORT_BY_URI_ASCENDING = 5;
const PRUint32 SORT_BY_URI_DESCENDING = 6;
const PRUint32 SORT_BY_VISITCOUNT_ASCENDING = 7;
const PRUint32 SORT_BY_VISITCOUNT_DESCENDING = 8;
/**
* "URL" results, one for each URL visited in the range.
* "URI" results, one for each URI visited in the range. Individual result
* nodes will be of type "URI".
*/
const PRUint32 RESULT_TYPE_URL = 0;
const PRUint32 RESULTS_AS_URI = 0;
/**
* "Visit" results, with one for each time a page was visited
* (this will often give you multiple results for one URL).
* "Visit" results, with one for each time a page was visited (this will
* often give you multiple results for one URI). Individual result nodes will
* have type "Visit"
*/
const PRUint32 RESULT_TYPE_VISIT = 1;
const PRUint32 RESULTS_AS_VISIT = 1;
/**
* This is identical to RESULT_TYPE_VISIT except that individual result nodes
* will have type "FullVisit". This is used for the attributes that are not
* commonly accessed to save space in the common case (the lists can be very
* long).
*/
const PRUint32 RESULTS_AS_FULL_VISIT = 2;
/**
* The grouping mode to be used for this query.
@ -591,22 +710,39 @@ interface nsINavHistoryQueryOptions : nsISupports
attribute PRUint32 sortingMode;
/**
* Sets the result type. One of RESULT_TYPE_*.
* Sets the result type. One of RESULT_TYPE_* which includes how URIs are
* represented.
*/
attribute PRUint32 resultType;
/**
* This option excludes all URIs from a bookmarks query. This would be used
* if you just wanted a list of bookmark folders and queries (such as the left
* pane of the places page). Ignored for queries over history.
* Defaults to false.
*/
attribute boolean excludeItems;
/**
* Set to true to exclude queries ("place:" URIs) from the query results.
* Simple folder queries (bookmark folder symlinks) will still be included.
* Defaults to false.
*/
attribute boolean excludeQueries;
/**
* When set, allows items with "place:" URIs to appear as containers,
* with the container's contents filled in from the stored query.
* If not set, these will appear as normal items.
* If not set, these will appear as normal items. Doesn't do anything if
* excludeQueries is set. Defaults to false.
*/
attribute boolean expandPlaces;
attribute boolean expandQueries;
/**
* Normally the title of a result will be the user's custom title if there is
* one, falling back on the default page title. If this is set, we will not
* do this operation and always use the original page title extracted from
* the HTML of the page.
* the HTML of the page. Defaults to false.
*/
attribute boolean forceOriginalTitle;
@ -615,7 +751,7 @@ interface nsINavHistoryQueryOptions : nsISupports
* user sees in the URL bar are not hidden. Hidden things include the content
* of iframes and all images on web pages. Normally, you don't want these
* things. If you do, set this flag and you'll get all items, even hidden
* ones.
* ones. Does nothing for bookmark queries. Defaults to false.
*/
attribute boolean includeHidden;
@ -685,8 +821,8 @@ interface nsINavHistoryService : nsISupports
/**
* This is just like markPageAsTyped (in nsIBrowserHistory, also implemented
* by the history service), but for bookmarks. It declares that the given URL
* is being opened as a result of following a bookmark. If this URL is loaded
* by the history service), but for bookmarks. It declares that the given URI
* is being opened as a result of following a bookmark. If this URI is loaded
* soon after this message has been received, that transition will be marked
* as following a bookmark.
*/
@ -715,7 +851,7 @@ interface nsINavHistoryService : nsISupports
* @param aHidden Whether the page is hidden. If the page has only
* TRANSITION_EMBED visits, this will be true, otherwise
* false.
* @param aTyped True if this URL has ever been typed.
* @param aTyped True if this URI has ever been typed.
*/
void setPageDetails(in nsIURI aURI, in AString aTitle, in AString aUserTitle,
in PRUint32 aVisitCount, in boolean aHidden,

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

View File

@ -54,18 +54,6 @@ treechildren::-moz-tree-image(title, open) {
-moz-image-region: rect(16px, 32px, 32px, 16px);
}
treechildren::-moz-tree-image(title, container, menu-root),
treechildren::-moz-tree-image(title, container, open, menu-root) {
list-style-image: url("chrome://browser/skin/places/icons.png") !important;
-moz-image-region: rect(0px, 16px, 17px, 0px);
}
treechildren::-moz-tree-image(title, container, toolbar-root),
treechildren::-moz-tree-image(title, container, open, toolbar-root) {
list-style-image: url("chrome://browser/skin/places/icons.png") !important;
-moz-image-region: rect(17px, 16px, 32px, 0px);
}
treechildren::-moz-tree-row(session-start) {
border-top:1px dotted ThreeDShadow;
}

View File

@ -114,6 +114,9 @@ static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);
#define KEY_LASTCHARSET_LOWER "last_charset"
#define KEY_ICON_LOWER "icon"
#define BOOKMARKS_MENU_ICON_URI "chrome://browser/skin/places/bookmarks_menu.png"
#define BOOKMARKS_TOOLBAR_ICON_URI "chrome://browser/skin/places/bookmarks_toolbar.png"
static const char kWhitespace[] = " \r\n\t\b";
class BookmarkImportFrame
@ -277,7 +280,8 @@ protected:
nsresult NewFrame();
nsresult PopFrame();
nsresult SetFaviconForURI(nsIURI* aURI, nsCString aData);
nsresult SetFaviconForURI(nsIURI* aURI, const nsCString& aData);
nsresult SetFaviconForFolder(PRInt64 aFolder, const nsACString& aFavicon);
};
@ -653,15 +657,19 @@ BookmarkContentSink::NewFrame()
// menu root
rv = mBookmarksService->GetBookmarksRoot(&ourID);
NS_ENSURE_SUCCESS(rv, rv);
if (mAllowRootChanges)
if (mAllowRootChanges) {
updateFolder = PR_TRUE;
SetFaviconForFolder(ourID, NS_LITERAL_CSTRING(BOOKMARKS_MENU_ICON_URI));
}
break;
case BookmarkImportFrame::Container_Toolbar:
// toolbar root
rv = mBookmarksService->GetToolbarRoot(&ourID);
NS_ENSURE_SUCCESS(rv, rv);
if (mAllowRootChanges)
if (mAllowRootChanges) {
updateFolder = PR_TRUE;
SetFaviconForFolder(ourID, NS_LITERAL_CSTRING(BOOKMARKS_TOOLBAR_ICON_URI));
}
break;
default:
NS_NOTREACHED("Unknown container type");
@ -704,7 +712,7 @@ BookmarkContentSink::PopFrame()
// should get expired when the page no longer references it.
nsresult
BookmarkContentSink::SetFaviconForURI(nsIURI* aURI, nsCString aData)
BookmarkContentSink::SetFaviconForURI(nsIURI* aURI, const nsCString& aData)
{
nsresult rv;
@ -779,6 +787,33 @@ BookmarkContentSink::SetFaviconForURI(nsIURI* aURI, nsCString aData)
}
// BookmarkContentSink::SetFaviconForFolder
//
// This sets the given favicon URI for the given folder. It is used to
// initialize the favicons for the bookmarks menu and toolbar. We don't
// actually set any data here because we assume the URI is a chrome: URI.
// These do not have to contain any data for them to work.
nsresult
BookmarkContentSink::SetFaviconForFolder(PRInt64 aFolder,
const nsACString& aFavicon)
{
nsFaviconService* faviconService = nsFaviconService::GetFaviconService();
NS_ENSURE_TRUE(faviconService, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIURI> folderURI;
nsresult rv = mBookmarksService->GetFolderURI(aFolder,
getter_AddRefs(folderURI));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> faviconURI;
rv = NS_NewURI(getter_AddRefs(faviconURI), aFavicon);
NS_ENSURE_SUCCESS(rv, rv);
return faviconService->SetFaviconUrlForPage(folderURI, faviconURI);
}
// SyncChannelStatus
//
// If a function returns an error, we need to set the channel status to be

View File

@ -156,7 +156,7 @@ nsNavBookmarks::Init()
getter_AddRefs(mBundle));
NS_ENSURE_SUCCESS(rv, rv);
// mDBFildURIBookmarks
// mDBFindURIBookmarks
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT a.* "
"FROM moz_bookmarks a, moz_history h "
@ -1068,38 +1068,58 @@ nsNavBookmarks::GetFolderType(PRInt64 aFolder, nsAString &aType)
return mDBGetFolderInfo->GetString(kGetFolderInfoIndex_Type, aType);
}
nsresult
nsNavBookmarks::ResultNodeForFolder(PRInt64 aID,
nsNavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode)
{
mozStorageStatementScoper scope(mDBGetFolderInfo);
mDBGetFolderInfo->BindInt64Parameter(0, aID);
PRBool results;
nsresult rv = mDBGetFolderInfo->ExecuteStep(&results);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(results, "ResultNodeForFolder expects a valid folder id");
// type (empty for normal ones, nonempty for container providers)
nsCAutoString folderType;
rv = mDBGetFolderInfo->GetUTF8String(kGetFolderInfoIndex_Type, folderType);
NS_ENSURE_SUCCESS(rv, rv);
// title
nsCAutoString title;
rv = mDBGetFolderInfo->GetUTF8String(kGetFolderInfoIndex_Title, title);
if (folderType.IsEmpty()) {
*aNode = new nsNavHistoryFolderResultNode(title, 0, 0, aOptions, aID);
if (! *aNode)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aNode);
} else {
// a container API thing
// FIXME(brettw)
//NS_NOTREACHED("FIXME: Not implemented");
*aNode = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
NS_IMETHODIMP
nsNavBookmarks::GetFolderURI(PRInt64 aFolder, nsIURI **aURI)
{
// Create a query for the folder; the URI is the querystring
// from that query.
nsresult rv;
nsNavHistory *history = History();
nsCOMPtr<nsINavHistoryQuery> query;
rv = history->GetNewQuery(getter_AddRefs(query));
NS_ENSURE_SUCCESS(rv, rv);
rv = query->SetFolders(&aFolder, 1);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINavHistoryQueryOptions> queryOptions;
rv = history->GetNewQueryOptions(getter_AddRefs(queryOptions));
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 groupByFolder = nsINavHistoryQueryOptions::GROUP_BY_FOLDER;
rv = queryOptions->SetGroupingMode(&groupByFolder, 1);
NS_ENSURE_SUCCESS(rv, rv);
nsCString folderURI;
rv = history->QueriesToQueryString((nsINavHistoryQuery **)&query,
1,
queryOptions,
folderURI);
NS_ENSURE_SUCCESS(rv, rv);
// Create a uri from the folder string.
rv = NS_NewURI(aURI, folderURI);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
// Create a query for the folder; the URI is the querystring from that
// query. We could create a proper query and serialize it, which might
// make it less prone to breakage since we'd only have one code path.
// However, this gets called a lot (every time we make a folder node)
// and constructing fake queries and options each time just to
// serialize them would be a waste. Therefore, we just synthesize the
// correct string here.
nsCAutoString spec("place:folders=");
spec.AppendInt(aFolder);
spec.AppendLiteral("&group=3"); // GROUP_BY_FOLDER
return NS_NewURI(aURI, spec);
}
NS_IMETHODIMP
@ -1124,144 +1144,53 @@ nsNavBookmarks::GetFolderReadonly(PRInt64 aFolder, PRBool *aResult)
}
nsresult
nsNavBookmarks::ResultNodeForFolder(PRInt64 aID,
nsINavHistoryQuery *aQuery,
nsINavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode)
{
// Create Query and QueryOptions objects to generate this folder's children
nsresult rv;
nsCOMPtr<nsINavHistoryQuery> query;
rv = aQuery->Clone(getter_AddRefs(query));
NS_ENSURE_SUCCESS(rv, rv);
query->SetFolders(&aID, 1);
nsCOMPtr<nsINavHistoryQueryOptions> options;
rv = aOptions->Clone(getter_AddRefs(options));
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsNavHistoryQueryNode> node = new nsNavHistoryQueryNode();
NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY);
node->mType = nsINavHistoryResultNode::RESULT_TYPE_QUERY;
node->mQueries = NS_STATIC_CAST(nsINavHistoryQuery**,
nsMemory::Alloc(sizeof(nsINavHistoryQuery*)));
NS_ENSURE_TRUE(node->mQueries, NS_ERROR_OUT_OF_MEMORY);
node->mQueries[0] = nsnull;
query.swap(node->mQueries[0]);
node->mQueryCount = 1;
node->mOptions = do_QueryInterface(options);
rv = FillFolderNode(aID, node);
NS_ENSURE_SUCCESS(rv, rv);
NS_ADDREF(*aNode = node);
return NS_OK;
}
nsresult
nsNavBookmarks::FillFolderNode(PRInt64 aID,
nsNavHistoryQueryNode *aNode)
{
mozStorageStatementScoper scope(mDBGetFolderInfo);
mDBGetFolderInfo->BindInt64Parameter(0, aID);
PRBool results;
nsresult rv = mDBGetFolderInfo->ExecuteStep(&results);
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(results, "ResultNodeForFolder expects a valid folder id");
// Fill in the folder type
// aNode->mFolderType should get set to the empty string
// if the folder type is null.
rv = mDBGetFolderInfo->GetString(kGetFolderInfoIndex_Type, aNode->mFolderType);
if (NS_FAILED(rv)) return rv;
// Fill in the folder title
return mDBGetFolderInfo->GetString(kGetFolderInfoIndex_Title, aNode->mTitle);
}
nsresult
nsNavBookmarks::QueryFolderChildren(nsINavHistoryQuery *aQuery,
nsINavHistoryQueryOptions *aOptions,
nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId,
nsNavHistoryQueryOptions *aOptions,
nsCOMArray<nsNavHistoryResultNode> *aChildren)
{
mozStorageTransaction transaction(DBConn(), PR_FALSE);
PRUint32 itemTypes;
aQuery->GetItemTypes(&itemTypes);
PRBool includeQueries = (itemTypes & nsINavHistoryQuery::INCLUDE_QUERIES) != 0;
PRBool includeItems = (itemTypes & nsINavHistoryQuery::INCLUDE_ITEMS) != 0;
nsresult rv;
nsCOMArray<nsNavHistoryResultNode> folderChildren;
{
mozStorageStatementScoper scope(mDBGetChildren);
mozStorageStatementScoper scope(mDBGetChildren);
PRInt64 *folders;
PRUint32 folderCount;
aQuery->GetFolders(&folderCount, &folders);
NS_ASSERTION(folderCount == 1, "querying > 1 folder not yet implemented");
rv = mDBGetChildren->BindInt64Parameter(0, aFolderId);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBGetChildren->BindInt64Parameter(0, folders[0]);
nsMemory::Free(folders);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBGetChildren->BindInt32Parameter(1, 0);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBGetChildren->BindInt32Parameter(1, 0);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBGetChildren->BindInt32Parameter(2, PR_INT32_MAX);
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBGetChildren->BindInt32Parameter(2, PR_INT32_MAX);
NS_ENSURE_SUCCESS(rv, rv);
PRBool results;
while (NS_SUCCEEDED(mDBGetChildren->ExecuteStep(&results)) && results) {
PRBool isFolder = !mDBGetChildren->IsNull(kGetChildrenIndex_FolderChild);
nsCOMPtr<nsNavHistoryResultNode> node;
if (isFolder) {
PRInt64 folder = mDBGetChildren->AsInt64(kGetChildrenIndex_FolderChild);
rv = ResultNodeForFolder(folder, aQuery,
aOptions, getter_AddRefs(node));
} else {
// need the concrete options for RowToResult
nsCOMPtr<nsNavHistoryQueryOptions> options =
do_QueryInterface(aOptions, &rv);
rv = History()->RowToResult(mDBGetChildren, options,
getter_AddRefs(node));
PRBool isQuery = IsQueryURI(node->URL());
if ((isQuery && !includeQueries) || (!isQuery && !includeItems)) {
continue;
}
}
PRBool results;
nsCOMPtr<nsNavHistoryQueryOptions> options = do_QueryInterface(aOptions, &rv);
while (NS_SUCCEEDED(mDBGetChildren->ExecuteStep(&results)) && results) {
PRBool isFolder = !mDBGetChildren->IsNull(kGetChildrenIndex_FolderChild);
nsCOMPtr<nsNavHistoryResultNode> node;
if (isFolder) {
PRInt64 folder = mDBGetChildren->AsInt64(kGetChildrenIndex_FolderChild);
rv = ResultNodeForFolder(folder, aOptions, getter_AddRefs(node));
if (NS_FAILED(rv))
continue;
} else {
rv = History()->RowToResult(mDBGetChildren, options,
getter_AddRefs(node));
NS_ENSURE_SUCCESS(rv, rv);
if (isFolder) {
NS_ENSURE_TRUE(folderChildren.AppendObject(node),
NS_ERROR_OUT_OF_MEMORY);
PRUint32 nodeType;
node->GetType(&nodeType);
if ((nodeType == nsINavHistoryResultNode::RESULT_TYPE_QUERY &&
aOptions->ExcludeQueries()) ||
(nodeType != nsINavHistoryResultNode::RESULT_TYPE_QUERY &&
nodeType != nsINavHistoryResultNode::RESULT_TYPE_FOLDER &&
aOptions->ExcludeItems())) {
continue;
}
NS_ENSURE_TRUE(aChildren->AppendObject(node), NS_ERROR_OUT_OF_MEMORY);
}
NS_ENSURE_TRUE(aChildren->AppendObject(node), NS_ERROR_OUT_OF_MEMORY);
}
// Now build children for any folder children we just created. This is
// pretty cheap (only go down 1 level) and allows us to know whether
// to draw a twisty.
static PRBool queryingChildren = PR_FALSE;
if (!queryingChildren) {
queryingChildren = PR_TRUE; // don't return before resetting to false
for (PRInt32 i = 0; i < folderChildren.Count(); ++i) {
PRBool built;
rv = folderChildren[i]->BuildChildren(&built);
if (NS_FAILED(rv)) {
break;
}
NS_ASSERTION(built, "new folder should not have already built children");
}
queryingChildren = PR_FALSE;
NS_ENSURE_SUCCESS(rv, rv);
}
return transaction.Commit();
}
@ -1297,11 +1226,11 @@ nsNavBookmarks::IsBookmarked(nsIURI *aURI, PRBool *aBookmarked)
}
NS_IMETHODIMP
nsNavBookmarks::GetBookmarkCategories(nsIURI *aURI, PRUint32 *aCount,
PRInt64 **aCategories)
nsNavBookmarks::GetBookmarkFolders(nsIURI *aURI, PRUint32 *aCount,
PRInt64 **aFolders)
{
*aCount = 0;
*aCategories = nsnull;
*aFolders = nsnull;
mozStorageStatementScoper scope(mDBFindURIBookmarks);
mozStorageTransaction transaction(DBConn(), PR_FALSE);
@ -1309,34 +1238,25 @@ nsNavBookmarks::GetBookmarkCategories(nsIURI *aURI, PRUint32 *aCount,
nsresult rv = BindStatementURI(mDBFindURIBookmarks, 0, aURI);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 arraySize = 8;
PRInt64 *categories = NS_STATIC_CAST(PRInt64*,
nsMemory::Alloc(arraySize * sizeof(PRInt64)));
NS_ENSURE_TRUE(categories, NS_ERROR_OUT_OF_MEMORY);
PRUint32 count = 0;
nsTArray<PRInt64> folders;
PRBool more;
while (NS_SUCCEEDED((rv = mDBFindURIBookmarks->ExecuteStep(&more))) && more) {
if (count >= arraySize) {
arraySize <<= 1;
PRInt64 *res = NS_STATIC_CAST(PRInt64*, nsMemory::Realloc(categories,
arraySize * sizeof(PRInt64)));
if (!res) {
delete categories;
return NS_ERROR_OUT_OF_MEMORY;
}
categories = res;
}
categories[count++] =
mDBFindURIBookmarks->AsInt64(kFindBookmarksIndex_Parent);
if (! folders.AppendElement(
mDBFindURIBookmarks->AsInt64(kFindBookmarksIndex_Parent)))
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ENSURE_SUCCESS(rv, rv);
*aCount = count;
*aCategories = categories;
if (folders.Length()) {
*aFolders = NS_STATIC_CAST(PRInt64*,
nsMemory::Alloc(sizeof(PRInt64) * folders.Length()));
if (! aFolders)
return NS_ERROR_OUT_OF_MEMORY;
for (PRUint32 i = 0; i < folders.Length(); i ++)
(*aFolders)[i] = folders[i];
}
*aCount = folders.Length();
return transaction.Commit();
}
@ -1448,7 +1368,7 @@ nsNavBookmarks::OnVisit(nsIURI *aURI, PRInt64 aVisitID, PRTime aTime,
IsBookmarked(aURI, &bookmarked);
if (bookmarked) {
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
OnItemVisited(aURI, aTime))
OnItemVisited(aURI, aVisitID, aTime))
}
return NS_OK;
}

View File

@ -65,24 +65,14 @@ public:
return sInstance;
}
// Creates a new result node for the given folder.
// The query and options are cloned, and the folder's id is set on the
// new node's query.
nsresult ResultNodeForFolder(PRInt64 aFolder,
nsINavHistoryQuery *aQuery,
nsINavHistoryQueryOptions *aOptions,
nsresult ResultNodeForFolder(PRInt64 aID, nsNavHistoryQueryOptions *aOptions,
nsNavHistoryResultNode **aNode);
// Fills in a ResultNode for the given folder.
// The node's type and queries must already be set.
nsresult FillFolderNode(PRInt64 aID,
nsNavHistoryQueryNode *aNode);
// Find all the children of a folder, using the given query and options.
// For each child, a ResultNode is created and added to |children|.
// The results are ordered by folder position.
nsresult QueryFolderChildren(nsINavHistoryQuery *aQuery,
nsINavHistoryQueryOptions *aOptions,
nsresult QueryFolderChildren(PRInt64 aFolderId,
nsNavHistoryQueryOptions *aOptions,
nsCOMArray<nsNavHistoryResultNode> *children);
// Returns a statement to get information about a folder id

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,7 @@
#include "nsIAutoCompleteSimpleResult.h"
#include "nsIBrowserHistory.h"
#include "nsICollation.h"
#include "nsIDateTimeFormat.h"
#include "nsIGlobalHistory.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
@ -80,13 +81,17 @@
// Size of visit count boost to give to urls which are sites or paths
#define AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST 5
#define QUERYUPDATE_TIME 0
#define QUERYUPDATE_SIMPLE 1
#define QUERYUPDATE_COMPLEX 2
#define QUERYUPDATE_COMPLEX_WITH_BOOKMARKS 3
class AutoCompleteIntermediateResultSet;
class mozIAnnotationService;
class nsNavHistory;
class nsNavBookmarks;
class QueryKeyValuePair;
// nsNavHistory
class nsNavHistory : public nsSupportsWeakReference,
@ -144,8 +149,20 @@ public:
return mDBConn;
}
// remember tree state
/**
* These functions return non-owning references to the locale-specific
* objects for places components. Guaranteed to return non-NULL.
*/
nsIStringBundle* GetBundle()
{ return mBundle; }
nsILocale* GetLocale()
{ return mLocale; }
nsICollation* GetCollation()
{ return mCollation; }
nsIDateTimeFormat* GetDateFormatter()
{ return mDateFormatter; }
// remember tree state
void SaveExpandItem(const nsAString& aTitle);
void SaveCollapseItem(const nsAString& aTitle);
@ -181,27 +198,24 @@ public:
static nsIAtom* sSessionStartAtom;
static nsIAtom* sSessionContinueAtom;
// this actually executes a query and gives you results, it is used by
// nsNavHistoryQueryResultNode
nsresult GetQueryResults(const nsCOMArray<nsINavHistoryQuery>& aQueries,
nsNavHistoryQueryOptions *aOptions,
nsCOMArray<nsNavHistoryResultNode>* aResults);
// Take a row of kGetInfoIndex_* columns and construct a ResultNode.
// The row must contain the full set of columns.
nsresult RowToResult(mozIStorageValueArray* aRow,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult);
// Take a row of kGetInfoIndex_* columns and fill in an existing ResultNode.
// The node's type must already be set, and the row must contain the full
// set of columns.
nsresult FillURLResult(mozIStorageValueArray* aRow,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode *aNode);
// Construct a new HistoryResult object. You can give it null query/options.
nsNavHistoryResult* NewHistoryResult(nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount,
nsNavHistoryQueryOptions* aOptions)
{
return new nsNavHistoryResult(this, mBundle, aQueries, aQueryCount,
aOptions);
}
nsresult VisitIdToResultNode(PRInt64 visitId,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult);
nsresult UriToResultNode(nsIURI* aUri,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryResultNode** aResult);
// used by other places components to send history notifications (for example,
// when the favicon has changed)
@ -218,6 +232,23 @@ public:
// well-known annotations used by the history and bookmarks systems
static const char kAnnotationPreviousEncoding[];
// used by query result nodes to update: see comment on body of CanLiveUpdateQuery
static PRUint32 GetUpdateRequirements(nsCOMArray<nsINavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions* aOptions,
PRBool* aHasSearchTerms);
PRBool EvaluateQueryForNode(nsCOMArray<nsINavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryURIResultNode* aNode);
static nsresult AsciiHostNameFromHostString(const nsACString& aHostName,
nsACString& aAscii);
static void DomainNameFromHostName(const nsCString& aHostName,
nsACString& aDomainName);
static PRTime NormalizeTime(PRUint32 aRelative, PRTime aOffset);
nsresult RecursiveGroup(const nsCOMArray<nsNavHistoryResultNode>& aSource,
const PRUint32* aGroupingMode, PRUint32 aGroupCount,
nsCOMArray<nsNavHistoryResultNode>* aDest);
private:
~nsNavHistory();
@ -254,6 +285,11 @@ protected:
nsCOMPtr<mozIStorageStatement> mDBRecentVisitOfURL; // converts URL into most recent visit ID/session ID
nsCOMPtr<mozIStorageStatement> mDBInsertVisit; // used by AddVisit
// these are used by VisitIdToResultNode for making new result nodes from IDs
nsCOMPtr<mozIStorageStatement> mDBVisitToURLResult; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBVisitToVisitResult; // kGetInfoIndex_* results
nsCOMPtr<mozIStorageStatement> mDBUrlToUrlResult; // kGetInfoIndex_* results
nsresult InitDB();
// this is the cache DB in memory used for storing visited URLs
@ -282,7 +318,6 @@ protected:
PRBool mNowValid;
nsCOMPtr<nsITimer> mExpireNowTimer;
static void expireNowTimerCallback(nsITimer* aTimer, void* aClosure);
PRTime NormalizeTime(PRUint32 aRelative, PRTime aOffset);
nsresult QueryToSelectClause(nsINavHistoryQuery* aQuery,
PRInt32 aStartParameter,
@ -293,27 +328,19 @@ protected:
nsINavHistoryQuery* aQuery,
PRInt32* aParamCount);
nsresult FillSimpleBookmarksQuery(nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount,
nsNavHistoryQueryOptions* aOptions,
nsINavHistoryResult** _retval);
nsresult ResultsAsList(mozIStorageStatement* statement,
nsNavHistoryQueryOptions* aOptions,
nsCOMArray<nsNavHistoryResultNode>* aResults);
void TitleForDomain(const nsString& domain, nsAString& aTitle);
void TitleForDomain(const nsCString& domain, nsACString& aTitle);
nsresult SetPageTitleInternal(nsIURI* aURI, PRBool aIsUserTitle,
const nsAString& aTitle);
nsresult RecursiveGroup(const nsCOMArray<nsNavHistoryResultNode>& aSource,
const PRUint32* aGroupingMode, PRUint32 aGroupCount,
nsCOMArray<nsNavHistoryResultNode>* aDest);
nsresult GroupByDay(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest);
nsresult GroupByHost(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest);
nsresult GroupByDomain(const nsCOMArray<nsNavHistoryResultNode>& aSource,
nsCOMArray<nsNavHistoryResultNode>* aDest);
nsCOMArray<nsNavHistoryResultNode>* aDest,
PRBool aIsDomain);
nsresult FilterResultSet(const nsCOMArray<nsNavHistoryResultNode>& aSet,
nsCOMArray<nsNavHistoryResultNode>* aFiltered,
@ -323,8 +350,11 @@ protected:
nsMaybeWeakPtrArray<nsINavHistoryObserver> mObservers;
PRInt32 mBatchesInProgress;
// string bundles
// localization
nsCOMPtr<nsIStringBundle> mBundle;
nsCOMPtr<nsILocale> mLocale;
nsCOMPtr<nsICollation> mCollation;
nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
// annotation service : MAY BE NULL!
//nsCOMPtr<mozIAnnotationService> mAnnotationService;

View File

@ -119,7 +119,7 @@ static void SetQueryKeyInt64(const nsCString& aValue, nsINavHistoryQuery* aQuery
// options setters
typedef NS_STDCALL_FUNCPROTO(nsresult, BoolOptionsSetter,
nsINavHistoryQueryOptions,
SetExpandPlaces, (PRBool));
SetExpandQueries, (PRBool));
typedef NS_STDCALL_FUNCPROTO(nsresult, Uint32OptionsSetter,
nsINavHistoryQueryOptions,
SetResultType, (PRUint32));
@ -130,7 +130,9 @@ static void SetOptionsKeyUint32(const nsCString& aValue,
nsINavHistoryQueryOptions* aOptions,
Uint32OptionsSetter setter);
// components of a query string
// Components of a query string.
// Note that query strings are also generated in nsNavBookmarks::GetFolderURI
// for performance reasons, so if you change these values, change that, too.
#define QUERYKEY_BEGIN_TIME "beginTime"
#define QUERYKEY_BEGIN_TIME_REFERENCE "beginTimeRef"
#define QUERYKEY_END_TIME "endTime"
@ -146,7 +148,9 @@ static void SetOptionsKeyUint32(const nsCString& aValue,
#define QUERYKEY_GROUP "group"
#define QUERYKEY_SORT "sort"
#define QUERYKEY_RESULT_TYPE "type"
#define QUERYKEY_EXPAND_PLACES "expandplaces"
#define QUERYKEY_EXCLUDE_ITEMS "excludeItems"
#define QUERYKEY_EXCLUDE_QUERIES "excludeQueries"
#define QUERYKEY_EXPAND_QUERIES "expandQueries"
#define QUERYKEY_FORCE_ORIGINAL_TITLE "originalTitle"
#define QUERYKEY_INCLUDE_HIDDEN "includeHidden"
#define QUERYKEY_MAX_RESULTS "maxResults"
@ -350,12 +354,30 @@ nsNavHistory::QueriesToQueryString(nsINavHistoryQuery **aQueries,
}
// result type
if (options->ResultType() != nsINavHistoryQueryOptions::RESULT_TYPE_URL) {
if (options->ResultType() != nsINavHistoryQueryOptions::RESULTS_AS_URI) {
AppendAmpersandIfNonempty(aQueryString);
aQueryString += NS_LITERAL_CSTRING(QUERYKEY_RESULT_TYPE "=");
AppendInt32(aQueryString, options->ResultType());
}
// exclude items
if (options->ExcludeItems()) {
AppendAmpersandIfNonempty(aQueryString);
aQueryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_ITEMS "=1");
}
// exclude queries
if (options->ExcludeQueries()) {
AppendAmpersandIfNonempty(aQueryString);
aQueryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_QUERIES "=1");
}
// expand queries
if (options->ExpandQueries()) {
AppendAmpersandIfNonempty(aQueryString);
aQueryString += NS_LITERAL_CSTRING(QUERYKEY_EXPAND_QUERIES "=1");
}
// title mode
if (options->ForceOriginalTitle()) {
AppendAmpersandIfNonempty(aQueryString);
@ -537,10 +559,20 @@ nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
SetOptionsKeyUint32(kvp.value, aOptions,
&nsINavHistoryQueryOptions::SetResultType);
// expand places
} else if (kvp.key.EqualsLiteral(QUERYKEY_EXPAND_PLACES)) {
// exclude items
} else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_ITEMS)) {
SetOptionsKeyBool(kvp.value, aOptions,
&nsINavHistoryQueryOptions::SetExpandPlaces);
&nsINavHistoryQueryOptions::SetExcludeItems);
// exclude queries
} else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_QUERIES)) {
SetOptionsKeyBool(kvp.value, aOptions,
&nsINavHistoryQueryOptions::SetExcludeQueries);
// expand queries
} else if (kvp.key.EqualsLiteral(QUERYKEY_EXPAND_QUERIES)) {
SetOptionsKeyBool(kvp.value, aOptions,
&nsINavHistoryQueryOptions::SetExpandQueries);
// force original title
} else if (kvp.key.EqualsLiteral(QUERYKEY_FORCE_ORIGINAL_TITLE)) {
@ -592,7 +624,7 @@ ParseQueryBooleanString(const nsCString& aString, PRBool* aValue)
// nsINavHistoryQuery **********************************************************
NS_IMPL_ISUPPORTS1(nsNavHistoryQuery, nsINavHistoryQuery)
NS_IMPL_ISUPPORTS2(nsNavHistoryQuery, nsNavHistoryQuery, nsINavHistoryQuery)
// nsINavHistoryQuery::nsNavHistoryQuery
//
@ -604,8 +636,7 @@ nsNavHistoryQuery::nsNavHistoryQuery()
: mBeginTime(0), mBeginTimeReference(TIME_RELATIVE_EPOCH),
mEndTime(0), mEndTimeReference(TIME_RELATIVE_EPOCH),
mOnlyBookmarked(PR_FALSE), mDomainIsHost(PR_FALSE),
mUriIsPrefix(PR_FALSE),
mItemTypes(PR_UINT32_MAX) // default to include all item types
mUriIsPrefix(PR_FALSE)
{
// differentiate not set (IsVoid) from empty string (local files)
mDomain.SetIsVoid(PR_TRUE);
@ -802,18 +833,6 @@ NS_IMETHODIMP nsNavHistoryQuery::SetFolders(const PRInt64 *aFolders,
return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::GetItemTypes(PRUint32 *aTypes)
{
*aTypes = mItemTypes;
return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetItemTypes(PRUint32 aTypes)
{
mItemTypes = aTypes;
return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::Clone(nsINavHistoryQuery** _retval)
{
*_retval = nsnull;
@ -904,23 +923,51 @@ nsNavHistoryQueryOptions::GetResultType(PRUint32* aType)
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetResultType(PRUint32 aType)
{
if (aType > RESULT_TYPE_VISIT)
if (aType > RESULTS_AS_FULL_VISIT)
return NS_ERROR_INVALID_ARG;
mResultType = aType;
return NS_OK;
}
// expandPlaces
// excludeItems
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetExpandPlaces(PRBool* aExpand)
nsNavHistoryQueryOptions::GetExcludeItems(PRBool* aExclude)
{
*aExpand = mExpandPlaces;
*aExclude = mExcludeItems;
return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetExpandPlaces(PRBool aExpand)
nsNavHistoryQueryOptions::SetExcludeItems(PRBool aExclude)
{
mExpandPlaces = aExpand;
mExcludeItems = aExclude;
return NS_OK;
}
// excludeQueries
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetExcludeQueries(PRBool* aExclude)
{
*aExclude = mExcludeQueries;
return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetExcludeQueries(PRBool aExclude)
{
mExcludeQueries = aExclude;
return NS_OK;
}
// expandQueries
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetExpandQueries(PRBool* aExpand)
{
*aExpand = mExpandQueries;
return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetExpandQueries(PRBool aExpand)
{
mExpandQueries = aExpand;
return NS_OK;
}
@ -997,7 +1044,9 @@ nsNavHistoryQueryOptions::Clone(nsNavHistoryQueryOptions **aResult)
} else {
result->mGroupCount = nsnull;
}
result->mExpandPlaces = mExpandPlaces;
result->mExcludeItems = mExcludeItems;
result->mExcludeQueries = mExcludeQueries;
result->mExpandQueries = mExpandQueries;
resultHolder.swap(*aResult);
return NS_OK;

View File

@ -50,15 +50,29 @@
// This class encapsulates the parameters for basic history queries for
// building UI, trees, lists, etc.
#define NS_NAVHISTORYQUERY_IID \
{ 0xb10185e0, 0x86eb, 0x4612, { 0x95, 0x7c, 0x09, 0x34, 0xf2, 0xb1, 0xce, 0xd7 } }
class nsNavHistoryQuery : public nsINavHistoryQuery
{
public:
nsNavHistoryQuery();
// note: we use a copy constructor in Clone(), the default is good enough
NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYQUERY_IID)
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYQUERY
PRTime BeginTime() { return mBeginTime; }
PRUint32 BeginTimeReference() { return mBeginTimeReference; }
PRTime EndTime() { return mEndTime; }
PRUint32 EndTimeReference() { return mEndTimeReference; }
const nsString& SearchTerms() { return mSearchTerms; }
PRBool OnlyBookmarked() { return mOnlyBookmarked; }
PRBool DomainIsHost() { return mDomainIsHost; }
const nsCString& Domain() { return mDomain; }
PRBool UriIsPrefix() { return mUriIsPrefix; }
nsIURI* Uri() { return mUri; } // NOT AddRef-ed!
const nsTArray<PRInt64>& Folders() const { return mFolders; }
private:
@ -77,7 +91,6 @@ protected:
PRBool mUriIsPrefix;
nsCOMPtr<nsIURI> mUri;
nsTArray<PRInt64> mFolders;
PRUint32 mItemTypes;
};
@ -91,7 +104,9 @@ class nsNavHistoryQueryOptions : public nsINavHistoryQueryOptions
public:
nsNavHistoryQueryOptions() : mSort(0), mResultType(0),
mGroupCount(0), mGroupings(nsnull),
mExpandPlaces(PR_FALSE),
mExcludeItems(PR_FALSE),
mExcludeQueries(PR_FALSE),
mExpandQueries(PR_FALSE),
mForceOriginalTitle(PR_FALSE),
mIncludeHidden(PR_FALSE),
mMaxResults(0)
@ -111,7 +126,9 @@ public:
const PRUint32* GroupingMode(PRUint32 *count) const {
*count = mGroupCount; return mGroupings;
}
PRBool ExpandPlaces() const { return mExpandPlaces; }
PRBool ExcludeItems() const { return mExcludeItems; }
PRBool ExcludeQueries() const { return mExcludeQueries; }
PRBool ExpandQueries() const { return mExpandQueries; }
PRBool ForceOriginalTitle() const { return mForceOriginalTitle; }
PRBool IncludeHidden() const { return mIncludeHidden; }
PRUint32 MaxResults() const { return mMaxResults; }
@ -123,11 +140,19 @@ private:
~nsNavHistoryQueryOptions() { delete[] mGroupings; }
// IF YOU ADD MORE ITEMS:
// * Add a new getter for C++ above if it makes sense
// * Add to the serialization code
// * Add to the deserialization code
// * Add to the nsNavHistoryQueryOptions::Clone() function
// * Add to the nsNavHistory.cpp:IsSimpleBookmarksQuery function if applicable
PRUint32 mSort;
PRUint32 mResultType;
PRUint32 mGroupCount;
PRUint32 *mGroupings;
PRBool mExpandPlaces;
PRBool mExcludeItems;
PRBool mExcludeQueries;
PRBool mExpandQueries;
PRBool mForceOriginalTitle;
PRBool mIncludeHidden;
PRUint32 mMaxResults;

File diff suppressed because it is too large Load Diff

View File

@ -45,17 +45,59 @@
#ifndef nsNavHistoryResult_h_
#define nsNavHistoryResult_h_
#include "nsTArray.h"
#include "nsInterfaceHashtable.h"
#include "nsDataHashtable.h"
class nsNavHistory;
class nsNavHistoryResult;
class nsIDateTimeFormat;
class nsIWritablePropertyBag;
class nsNavHistoryQueryOptions;
class nsNavHistoryContainerResultNode;
class nsNavHistoryFolderResultNode;
class nsNavHistoryQueryResultNode;
class nsNavHistoryURIResultNode;
class nsNavHistoryVisitResultNode;
/**
* hashkey wrapper using PRInt64 KeyType
*
* @see nsTHashtable::EntryType for specification
*
* This just truncates the 64-bit int to a 32-bit one for using a hash number.
* It is used for bookmark folder IDs, which should be way less than 2^32.
*/
class nsTrimInt64HashKey : public PLDHashEntryHdr
{
public:
typedef const PRInt64& KeyType;
typedef const PRInt64* KeyTypePointer;
nsTrimInt64HashKey(KeyTypePointer aKey) : mValue(*aKey) { }
nsTrimInt64HashKey(const nsTrimInt64HashKey& toCopy) : mValue(toCopy.mValue) { }
~nsTrimInt64HashKey() { }
KeyType GetKey() const { return mValue; }
KeyTypePointer GetKeyPointer() const { return &mValue; }
PRBool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(KeyTypePointer aKey)
{ return NS_STATIC_CAST(PRUint32, (*aKey) & PR_UINT32_MAX); }
enum { ALLOW_MEMMOVE = PR_TRUE };
private:
const PRInt64 mValue;
};
// Declare methods for implementing nsINavBookmarkObserver
// and nsINavHistoryObserver (some methods, such as BeginUpdateBatch overlap)
#define NS_DECL_BOOKMARK_HISTORY_OBSERVER \
NS_DECL_NSINAVBOOKMARKOBSERVER \
NS_IMETHOD OnVisit(nsIURI* aURI, PRInt64 aVisitID, PRTime aTime, \
PRInt64 aSessionID, PRInt64 aReferringID, \
NS_IMETHOD OnVisit(nsIURI* aURI, PRInt64 aVisitId, PRTime aTime, \
PRInt64 aSessionId, PRInt64 aReferringId, \
PRUint32 aTransitionType); \
NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle, \
const nsAString& aUserTitle, \
@ -74,10 +116,38 @@ class nsNavHistoryQueryOptions;
#define NS_NAVHISTORYRESULTNODE_IID \
{0x54b61d38, 0x57c1, 0x11da, {0x95, 0xb8, 0x00, 0x13, 0x21, 0xc9, 0xf6, 0x9e}}
// These are all the simple getters, they can be used for the result node
// implementation and all subclasses. More complex are GetIcon and GetParent
// (which depends on the definition of container result node).
#define NS_IMPLEMENT_SIMPLE_RESULTNODE \
NS_IMETHOD GetTitle(nsACString& aTitle) \
{ aTitle = mTitle; return NS_OK; } \
NS_IMETHOD GetAccessCount(PRUint32* aAccessCount) \
{ *aAccessCount = mAccessCount; return NS_OK; } \
NS_IMETHOD GetTime(PRTime* aTime) \
{ *aTime = mTime; return NS_OK; } \
NS_IMETHOD GetIndentLevel(PRUint32* aIndentLevel) \
{ *aIndentLevel = mIndentLevel; return NS_OK; }
// This is used by the base classes instead of
// NS_FORWARD_NSINAVHISTORYRESULTNODE(nsNavHistoryResultNode) because they
// need to redefine GetType rather than forwarding it. This implements all the
// simple getters instead of forwarding because they are so short and we can
// save a virtual function call.
#define NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE \
NS_IMPLEMENT_SIMPLE_RESULTNODE \
NS_IMETHOD GetIcon(nsIURI** aIcon) \
{ return nsNavHistoryResultNode::GetIcon(aIcon); } \
NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) \
{ return nsNavHistoryResultNode::GetParent(aParent); } \
NS_IMETHOD GetPropertyBag(nsIWritablePropertyBag** aBag) \
{ return nsNavHistoryResultNode::GetPropertyBag(aBag); }
class nsNavHistoryResultNode : public nsINavHistoryResultNode
{
public:
nsNavHistoryResultNode();
nsNavHistoryResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI);
#ifdef MOZILLA_1_8_BRANCH
NS_DEFINE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULTNODE_IID)
@ -86,116 +156,449 @@ public:
#endif
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYRESULTNODE
NS_IMPLEMENT_SIMPLE_RESULTNODE
NS_IMETHOD GetIcon(nsIURI** aIcon);
NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent);
NS_IMETHOD GetPropertyBag(nsIWritablePropertyBag** aBag);
// leave GetType() unimplemented, will be implemented by sub classes
// History/bookmark notifications. Note that we don't actually inherit
// these interfaces since multiple-inheritance breaks nsCOMArray.
NS_DECL_BOOKMARK_HISTORY_OBSERVER
virtual void OnRemoving();
// Generate the children for this node.
virtual nsresult BuildChildren(PRBool *aBuilt) {
*aBuilt = PR_FALSE;
return NS_OK;;
}
public:
// Rebuild the node's data. This only applies to nodes which have
// a URL or a folder ID, and does _not_ rebuild the node's children.
virtual nsresult Rebuild();
// Non-XPCOM member accessors
PRInt32 Type() const { return mType; }
const nsCString& URL() const { return mUrl; }
virtual PRInt64 FolderId() const { return 0; }
PRInt32 VisibleIndex() const { return mVisibleIndex; }
void SetVisibleIndex(PRInt32 aIndex) { mVisibleIndex = aIndex; }
PRInt32 IndentLevel() const { return mIndentLevel; }
void SetIndentLevel(PRInt32 aLevel) { mIndentLevel = aLevel; }
nsNavHistoryResultNode* Parent() { return mParent; }
void SetParent(nsNavHistoryResultNode *aParent) { mParent = aParent; }
nsNavHistoryResultNode* ChildAt(PRInt32 aIndex) { return mChildren[aIndex]; }
protected:
virtual ~nsNavHistoryResultNode() {}
// Find the top-level NavHistoryResult for this node
nsNavHistoryResult* GetResult();
// parent of this element, NULL if no parent. Filled in by FilledAllResults
// in the result set.
nsNavHistoryResultNode* mParent;
// These functions test the type. We don't use a virtual function since that
// would take a vtable slot for every one of (potentially very many) nodes.
// Note that GetType() already has a vtable slot because its on the iface.
PRBool IsTypeContainer(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
type == nsINavHistoryResultNode::RESULT_TYPE_DAY ||
type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER);
}
PRBool IsContainer() {
PRUint32 type;
GetType(&type);
return IsTypeContainer(type);
}
static PRBool IsTypeQuerySubcontainer(PRUint32 type) {
// Tests containers that are inside queries that really belong to the query
// itself, and is used when recursively updating a query. This include host
// and day containers, but doesn't include other queries and folders.
return (type == nsINavHistoryResultNode::RESULT_TYPE_HOST ||
type == nsINavHistoryResultNode::RESULT_TYPE_DAY);
}
PRBool IsQuerySubcontainer() {
PRUint32 type;
GetType(&type);
return IsTypeQuerySubcontainer(type);
}
static PRBool IsTypeURI(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_URI ||
type == nsINavHistoryResultNode::RESULT_TYPE_VISIT ||
type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT);
}
PRBool IsURI() {
PRUint32 type;
GetType(&type);
return IsTypeURI(type);
}
static PRBool IsTypeVisit(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_VISIT ||
type == nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT);
}
PRBool IsVisit() {
PRUint32 type;
GetType(&type);
return IsTypeVisit(type);
}
static PRBool IsTypeFolder(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER);
}
PRBool IsFolder() {
PRUint32 type;
GetType(&type);
return IsTypeFolder(type);
}
static PRBool IsTypeQuery(PRUint32 type) {
return (type == nsINavHistoryResultNode::RESULT_TYPE_QUERY);
}
PRBool IsQuery() {
PRUint32 type;
GetType(&type);
return IsTypeQuery(type);
}
// these are all the basic row info, filled in by nsNavHistory::RowToResult
PRInt64 mID; // keep this for comparing dups, not exposed in interface
// might be 0, indicating some kind of parent node
PRInt32 mType;
nsCString mUrl;
nsString mTitle;
PRInt32 mAccessCount;
PRTime mTime;
nsString mHost;
nsCString mFaviconURL;
PRInt64 mSessionID;
nsNavHistoryContainerResultNode* GetAsContainer() {
NS_ASSERTION(IsContainer(), "Not a container");
return NS_REINTERPRET_CAST(nsNavHistoryContainerResultNode*, this);
}
nsNavHistoryURIResultNode* GetAsURI() {
NS_ASSERTION(IsURI(), "Not a URI");
return NS_REINTERPRET_CAST(nsNavHistoryURIResultNode*, this);
}
nsNavHistoryVisitResultNode* GetAsVisit() {
NS_ASSERTION(IsVisit(), "Not a visit");
return NS_REINTERPRET_CAST(nsNavHistoryVisitResultNode*, this);
}
nsNavHistoryFolderResultNode* GetAsFolder() {
NS_ASSERTION(IsFolder(), "Not a folder");
return NS_REINTERPRET_CAST(nsNavHistoryFolderResultNode*, this);
}
nsNavHistoryQueryResultNode* GetAsQuery() {
NS_ASSERTION(IsQuery(), "Not a query");
return NS_REINTERPRET_CAST(nsNavHistoryQueryResultNode*, this);
}
// Filled in by the result type generator in nsNavHistory
nsCOMArray<nsNavHistoryResultNode> mChildren;
nsNavHistoryContainerResultNode* mParent;
nsCString mTitle;
PRUint32 mAccessCount;
PRInt64 mTime;
nsCString mFaviconURI;
// filled in by FillledAllResults in the result set.
// The indent level of this node. The root node will have a value of -1. The
// root's children will have a value of 0, and so on.
PRInt32 mIndentLevel;
// index of this element into the mVisibleElements array in the result set
// The index into the result's mVisibleElements list of this element. This is
// -1 if it is invalid. For items, >= 0 can be used to determine if the node
// is visible in the list or not. For folders, call IsVisible, since they
// can be the root node which is not itself visible, but its children are.
PRInt32 mVisibleIndex;
};
// nsNavHistoryURIResultNode
#define NS_IMPLEMENT_URIRESULT \
NS_IMETHOD GetUri(nsACString& aURI) { aURI = mURI; return NS_OK; }
class nsNavHistoryURIResultNode : public nsNavHistoryResultNode,
public nsINavHistoryURIResultNode
{
public:
nsNavHistoryURIResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI, const nsACString& aURI);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsINavHistoryResultNode::RESULT_TYPE_URI; return NS_OK; }
NS_IMPLEMENT_URIRESULT
public:
nsCString mURI;
};
// nsNavHistoryVisitResultNode
#define NS_IMPLEMENT_VISITRESULT \
NS_IMPLEMENT_URIRESULT \
NS_IMETHOD GetSessionId(PRInt64* aSessionId) \
{ *aSessionId = mSessionId; return NS_OK; }
class nsNavHistoryVisitResultNode : public nsNavHistoryURIResultNode,
public nsINavHistoryVisitResultNode
{
public:
nsNavHistoryVisitResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI, const nsACString& aURI,
PRInt64 aSession);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsINavHistoryResultNode::RESULT_TYPE_VISIT; return NS_OK; }
NS_IMPLEMENT_VISITRESULT
public:
PRInt64 mSessionId;
};
// nsNavHistoryFullVisitResultNode
#define NS_IMPLEMENT_FULLVISITRESULT \
NS_IMPLEMENT_VISITRESULT \
NS_IMETHOD GetVisitId(PRInt64 *aVisitId) \
{ *aVisitId = mVisitId; return NS_OK; } \
NS_IMETHOD GetReferringVisitId(PRInt64 *aReferringVisitId) \
{ *aReferringVisitId = mReferringVisitId; return NS_OK; } \
NS_IMETHOD GetTransitionType(PRInt32 *aTransitionType) \
{ *aTransitionType = mTransitionType; return NS_OK; }
class nsNavHistoryFullVisitResultNode : public nsNavHistoryVisitResultNode,
public nsINavHistoryFullVisitResultNode
{
public:
nsNavHistoryFullVisitResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI, const nsACString& aURI,
PRInt64 aSession, PRInt64 aVisitId, PRInt64 aReferringVisitId,
PRInt32 aTransitionType);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsINavHistoryResultNode::RESULT_TYPE_FULL_VISIT; return NS_OK; }
NS_IMPLEMENT_FULLVISITRESULT
public:
PRInt64 mVisitId;
PRInt64 mReferringVisitId;
PRInt32 mTransitionType;
};
// nsNavHistoryContainerResultNode
//
// This is the base class for all nodes that can have children. It is
// overridden for nodes that are dynamically populated such as queries and
// folders. It is used directly for simple containers such as host groups
// in history views.
// derived classes each provide their own implementation of has children and
// forward the rest to us using this macro
#define NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN \
NS_IMETHOD GetContainerOpen(PRBool *aContainerOpen) \
{ return nsNavHistoryContainerResultNode::GetContainerOpen(aContainerOpen); } \
NS_IMETHOD SetContainerOpen(PRBool aContainerOpen) \
{ return nsNavHistoryContainerResultNode::SetContainerOpen(aContainerOpen); } \
NS_IMETHOD GetChildCount(PRUint32 *aChildCount) \
{ return nsNavHistoryContainerResultNode::GetChildCount(aChildCount); } \
NS_IMETHOD GetChild(PRUint32 index, nsINavHistoryResultNode **_retval) \
{ return nsNavHistoryContainerResultNode::GetChild(index, _retval); } \
NS_IMETHOD GetChildrenReadOnly(PRBool *aChildrenReadOnly) \
{ return nsNavHistoryContainerResultNode::GetChildrenReadOnly(aChildrenReadOnly); }
class nsNavHistoryContainerResultNode : public nsNavHistoryResultNode,
public nsINavHistoryContainerResultNode
{
public:
nsNavHistoryContainerResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI, PRUint32 aContainerType,
PRBool aReadOnly);
nsNavHistoryContainerResultNode(const nsACString& aTitle,
const nsACString& aIconURI, PRUint32 aContainerType);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE
NS_IMETHOD GetType(PRUint32* type)
{ *type = mContainerType; return NS_OK; }
NS_DECL_NSINAVHISTORYCONTAINERRESULTNODE
public:
virtual void OnRemoving();
PRBool AreChildrenVisible();
// overridded by descendents to populate
virtual nsresult OpenContainer();
virtual nsresult CloseContainer();
// this points to the result that owns this container. All containers have
// their result pointer set so we can quickly get to the result without having
// to walk the tree. Yet, this also saves us from storing a million pointers
// for every leaf node to the result.
nsNavHistoryResult* mResult;
// for example, RESULT_TYPE_HOST or RESULT_TYPE_DAY. Query and Folder results
// override GetType so this is not used, but is still kept in sync.
PRUint32 mContainerType;
// when there are children, this stores the open state in the tree
// this is set to the default in the constructor
PRBool mExpanded;
friend class nsNavHistory;
friend class nsNavHistoryResult;
friend class nsNavBookmarks;
// Filled in by the result type generator in nsNavHistory
nsCOMArray<nsNavHistoryResultNode> mChildren;
PRBool mChildrenReadOnly;
void FillStats();
void ReverseUpdateStats(PRInt32 aAccessCountChange);
// sorting
typedef nsCOMArray<nsNavHistoryResultNode>::nsCOMArrayComparatorFunc SortComparator;
virtual PRUint32 GetSortType();
static SortComparator GetSortingComparator(PRUint32 aSortType);
void RecursiveSort(nsICollation* aCollation, SortComparator aComparator);
PRUint32 FindInsertionPoint(nsNavHistoryResultNode* aNode, SortComparator aComparator);
PRBool DoesChildNeedResorting(PRUint32 aIndex, SortComparator aComparator);
PR_STATIC_CALLBACK(int) SortComparison_TitleLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_TitleGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_DateLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_DateGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_URILess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_URIGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_VisitCountLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_VisitCountGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
// finding children: THESE DO NOT ADDREF
nsNavHistoryURIResultNode* FindChildURI(nsIURI* aURI, PRUint32* aNodeIndex)
{
nsCAutoString spec;
if (NS_FAILED(aURI->GetSpec(spec)))
return PR_FALSE;
return FindChildURI(spec, aNodeIndex);
}
nsNavHistoryURIResultNode* FindChildURI(const nsACString& aSpec,
PRUint32* aNodeIndex);
nsNavHistoryFolderResultNode* FindChildFolder(PRInt64 aFolderId,
PRUint32* aNodeIndex);
nsNavHistoryContainerResultNode* FindChildContainerByName(const nsACString& aTitle,
PRUint32* aNodeIndex);
// returns the index of the given node, -1 if not found
PRInt32 FindChild(nsNavHistoryResultNode* aNode)
{ return mChildren.IndexOf(aNode); }
nsresult InsertChildAt(nsNavHistoryResultNode* aNode, PRInt32 aIndex,
PRBool aIsTemporary = PR_FALSE);
nsresult InsertSortedChild(nsNavHistoryResultNode* aNode,
PRBool aIsTemporary = PR_FALSE);
void MergeResults(nsCOMArray<nsNavHistoryResultNode>* aNodes);
nsresult ReplaceChildURIAt(PRUint32 aIndex,
nsNavHistoryURIResultNode* aNode);
nsresult RemoveChildAt(PRInt32 aIndex, PRBool aIsTemporary = PR_FALSE);
};
// nsNavHistoryQeuryNode
//
// nsNavHistoryQueryNode is a special type of ResultNode that executes a
// query when asked to build its children.
class nsNavHistoryQueryNode : public nsNavHistoryResultNode
// nsNavHistoryQueryResultNode
//
// Overridden container type for complex queries over history and/or
// bookmarks. This keeps itself in sync by listening to history and
// bookmark notifications.
class nsNavHistoryQueryResultNode : public nsNavHistoryContainerResultNode,
public nsINavHistoryQueryResultNode
{
public:
nsNavHistoryQueryNode()
: mQueries(nsnull), mQueryCount(0), mBuiltChildren(PR_FALSE) {}
nsNavHistoryQueryResultNode(nsNavHistoryQueryOptions* aGeneratingOptions,
const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI,
const nsACString& aQueryURI);
nsNavHistoryQueryResultNode(nsNavHistoryQueryOptions* aGeneratingOptions,
const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, const nsACString& aIconURI,
nsINavHistoryQuery** aQueries, PRUint32 aQueryCount,
nsNavHistoryQueryOptions* aOptions);
// nsINavHistoryResultNode methods
NS_IMETHOD GetFolderId(PRInt64 *aId)
{ *aId = nsNavHistoryQueryNode::FolderId(); return NS_OK; }
NS_IMETHOD GetFolderType(nsAString& aFolderType);
NS_IMETHOD GetQueries(PRUint32 *aQueryCount,
nsINavHistoryQuery ***aQueries);
NS_IMETHOD GetQueryOptions(nsINavHistoryQueryOptions **aOptions);
NS_IMETHOD GetChildrenReadOnly(PRBool *aResult);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsINavHistoryResultNode::RESULT_TYPE_QUERY; return NS_OK; }
NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN
NS_IMETHOD GetHasChildren(PRBool* aHasChildren);
NS_DECL_NSINAVHISTORYQUERYRESULTNODE
PRBool CanExpand();
virtual nsresult OpenContainer();
NS_DECL_BOOKMARK_HISTORY_OBSERVER
virtual void OnRemoving();
// nsNavHistoryResultNode methods
virtual nsresult BuildChildren(PRBool *aBuilt);
virtual PRInt64 FolderId() const;
virtual nsresult Rebuild();
public:
// These are the options that caused this node to be generated. For just
// running queries directly, this node will be the root of the result and
// mGeneratingOptions will be the same as mOptions. When queries are in
// bookmark folders, this it the options structure used to generate the
// bookmarks tree. It tells us, for example, if we should expand ourselves.
nsCOMPtr<nsNavHistoryQueryOptions> mGeneratingOptions;
protected:
virtual ~nsNavHistoryQueryNode();
nsresult ParseQueries();
nsresult CreateNode(nsIURI *aURI, nsNavHistoryResultNode **aNode);
nsresult UpdateQuery();
PRBool HasFilteredChildren() const;
// this may be constructedlazily from mQueries and mOptions, call VerifyQueriesSerialized
// either this or mQueries/mOptions should be valid
nsCString mQueryURI;
nsresult VerifyQueriesSerialized();
nsINavHistoryQuery **mQueries;
PRUint32 mQueryCount;
// these may be constructed lazily from mQueryURI, call VerifyQueriesParsed
// either this or mQueryURI should be valid
nsCOMArray<nsINavHistoryQuery> mQueries;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
PRBool mBuiltChildren;
nsString mFolderType;
PRUint32 mLiveUpdate; // one of QUERYUPDATE_* in nsNavHistory.h
PRBool mHasSearchTerms;
nsresult VerifyQueriesParsed();
friend class nsNavBookmarks;
// this indicates whether the query contents are valid, they don't go away
// after the container is closed until a notification comes in
PRBool mContentsValid;
PRBool mBatchInProgress;
nsresult FillChildren();
void ClearChildren(PRBool unregister);
nsresult Refresh();
virtual PRUint32 GetSortType();
void UpdateURIs(PRBool aOnlyOne, PRBool aUpdateSort, const nsCString& aSpec,
void (*aCallback)(nsNavHistoryURIResultNode*,void*),
void* aClosure);
void RecursiveFindURIs(PRBool aOnlyOne,
nsNavHistoryContainerResultNode* aContainer,
const nsCString& aSpec,
nsCOMArray<nsNavHistoryResultNode>* aMatches);
};
// nsNavHistoryFolderResultNode
//
// Overridden container type for bookmark folders. It will keep the contents
// of the folder in sync with the bookmark service.
class nsNavHistoryFolderResultNode : public nsNavHistoryContainerResultNode,
public nsINavHistoryFolderResultNode
{
public:
nsNavHistoryFolderResultNode(const nsACString& aTitle, PRUint32 aAccessCount,
PRTime aTime, nsNavHistoryQueryOptions* options,
PRInt64 aFolderId);
NS_DECL_ISUPPORTS_INHERITED
NS_FORWARD_RESULTNODE_TO_BASE_EXCEPT_GETTYPE
NS_IMETHOD GetType(PRUint32* type)
{ *type = nsINavHistoryResultNode::RESULT_TYPE_FOLDER; return NS_OK; }
NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN
NS_IMETHOD GetHasChildren(PRBool* aHasChildren);
NS_DECL_NSINAVHISTORYQUERYRESULTNODE
NS_IMETHOD GetFolderId(PRInt64* aFolderId)
{ *aFolderId = mFolderId; return NS_OK; }
virtual nsresult OpenContainer();
// This object implements a bookmark observer interface without deriving from
// the bookmark observers. This is called from the result's actual observer
// and it knows all observers are FolderResultNodes
NS_DECL_NSINAVBOOKMARKOBSERVER
virtual void OnRemoving();
public:
// this indicates whether the folder contents are valid, they don't go away
// after the container is closed until a notification comes in
PRBool mContentsValid;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
PRInt64 mFolderId;
nsresult FillChildren();
void ClearChildren(PRBool aUnregister);
virtual PRUint32 GetSortType();
PRBool StartIncrementalUpdate();
};
@ -208,151 +611,121 @@ protected:
// This object implements nsITreeView so you can just set it to a tree
// view and it will work. This object also observes the necessary history
// and bookmark events to keep itself up-to-date.
//
class nsNavHistoryResult : public nsNavHistoryQueryNode,
public nsSupportsWeakReference,
class nsNavHistoryResult : public nsSupportsWeakReference,
public nsINavHistoryResult,
public nsITreeView,
public nsINavBookmarkObserver,
public nsINavHistoryObserver
{
public:
nsNavHistoryResult(nsNavHistory* aHistoryService,
nsIStringBundle* aHistoryBundle,
nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount,
nsNavHistoryQueryOptions *aOptions);
static nsresult NewHistoryResult(nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount,
nsNavHistoryQueryOptions* aOptions,
nsNavHistoryContainerResultNode* aRoot,
nsNavHistoryResult** result);
// Two-stage init, MUST BE CALLED BEFORE ANYTHING ELSE
nsresult Init();
nsresult PropertyBagFor(nsISupports* aObject,
nsIWritablePropertyBag** aBag);
nsCOMArray<nsNavHistoryResultNode>* GetTopLevel() { return &mChildren; }
void ApplyTreeState(const nsDataHashtable<nsStringHashKey, int>& aExpanded);
void FilledAllResults();
nsresult BuildChildrenFor(nsNavHistoryResultNode *aNode);
// These methods are typically called by child nodes from one of the
// history or bookmark observer notifications.
// Notify the result that the entire contents of the tree have changed.
void Invalidate();
// Notify the result that a row has been added at index aIndex relative
// to aParent.
void RowAdded(nsNavHistoryResultNode* aParent, PRInt32 aIndex);
// Notify the result that the row with visible index aVisibleIndex has been
// removed from the tree.
void RowRemoved(PRInt32 aVisibleIndex);
// Notify the result that the contents of the row at visible index
// aVisibleIndex has been modified.
void RowChanged(PRInt32 aVisibleIndex);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_ISUPPORTS
NS_DECL_NSINAVHISTORYRESULT
NS_DECL_NSITREEVIEW
NS_FORWARD_NSINAVBOOKMARKOBSERVER(nsNavHistoryQueryNode::)
NS_IMETHOD OnVisit(nsIURI* aURI, PRInt64 aVisitID, PRTime aTime,
PRInt64 aSessionID, PRInt64 aReferringID,
PRUint32 aTransitionType)
{ return nsNavHistoryQueryNode::OnVisit(aURI, aVisitID, aTime, aSessionID,
aReferringID, aTransitionType); }
NS_IMETHOD OnDeleteURI(nsIURI *aURI)
{ return nsNavHistoryQueryNode::OnDeleteURI(aURI); }
NS_IMETHOD OnClearHistory()
{ return nsNavHistoryQueryNode::OnClearHistory(); }
NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle,
const nsAString& aUserTitle,
PRBool aIsUserTitleChanged)
{ return nsNavHistoryQueryNode::OnTitleChanged(aURI, aPageTitle, aUserTitle,
aIsUserTitleChanged); }
NS_IMETHOD OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
const nsAString &aValue)
{ return nsNavHistoryQueryNode::OnPageChanged(aURI, aWhat, aValue); }
NS_DECL_BOOKMARK_HISTORY_OBSERVER
NS_FORWARD_NSINAVHISTORYRESULTNODE(nsNavHistoryQueryNode::)
// called by container nodes to update the tree when things change
nsresult RefreshVisibleSection(nsNavHistoryContainerResultNode* aContainer);
private:
void AddEverythingObserver(nsNavHistoryQueryResultNode* aNode);
void AddBookmarkObserver(nsNavHistoryFolderResultNode* aNode, PRInt64 aFolder);
void RemoveEverythingObserver(nsNavHistoryQueryResultNode* aNode);
void RemoveBookmarkObserver(nsNavHistoryFolderResultNode* aNode, PRInt64 aFolder);
PRBool CanCollapseDuplicates(nsNavHistoryResultNode* aTop,
nsNavHistoryResultNode* aNext,
PRUint32* aShowThisOne);
public:
// two-stage init, use NewHistoryResult to construct
nsNavHistoryResult(nsNavHistoryContainerResultNode* mRoot);
~nsNavHistoryResult();
nsresult Init(nsINavHistoryQuery** aQueries,
PRUint32 aQueryCount,
nsNavHistoryQueryOptions *aOptions);
nsCOMPtr<nsIStringBundle> mBundle;
nsCOMPtr<nsITreeBoxObject> mTree; // may be null if no tree has bound itself
nsCOMPtr<nsITreeSelection> mSelection; // may be null
nsRefPtr<nsNavHistoryContainerResultNode> mRootNode;
nsRefPtr<nsNavHistory> mHistoryService;
nsCOMArray<nsINavHistoryQuery> mQueries;
nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
// One of nsNavHistoryQueryOptions.SORY_BY_* This is initialized to mOptions.sortingMode,
// but may be overridden if the user clicks on one of the columns.
PRUint32 mSortingMode;
PRBool mCollapseDuplicates;
nsMaybeWeakPtrArray<nsINavHistoryResultViewObserver> mObservers;
// for locale-specific date formatting and string sorting
nsCOMPtr<nsILocale> mLocale;
nsCOMPtr<nsICollation> mCollation;
nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
// this is the flattened version of the hierarchy containing everything
nsVoidArray mAllElements;
nsNavHistoryResultNode* AllElementAt(PRInt32 index)
{
return (nsNavHistoryResultNode*)mAllElements[index];
}
nsVoidArray mVisibleElements;
nsNavHistoryResultNode* VisibleElementAt(PRInt32 index)
{
return (nsNavHistoryResultNode*)mVisibleElements[index];
}
// This value indicates whether we should try to compute session boundaries.
// It is cached so we don't have to compute it every time we want to get a
// row style.
PRBool mShowSessions;
void ComputeShowSessions();
void FillTreeStats(nsNavHistoryResultNode* aResult, PRInt32 aLevel);
void InitializeVisibleList();
void RebuildList();
void RebuildAllListRecurse(const nsCOMArray<nsNavHistoryResultNode>& aSource);
void BuildVisibleSection(const nsCOMArray<nsNavHistoryResultNode>& aSources,
nsVoidArray* aVisible);
void InsertVisibleSection(const nsVoidArray& aAddition, PRInt32 aInsertHere);
PRInt32 DeleteVisibleChildrenOf(PRInt32 aIndex);
// property bags for all result nodes, see PropertyBagFor
nsInterfaceHashtable<nsISupportsHashKey, nsIWritablePropertyBag> mPropertyBags;
void RecursiveSortArray(nsCOMArray<nsNavHistoryResultNode>& aSources,
PRUint32 aSortingMode);
void SetTreeSortingIndicator();
nsCOMPtr<nsITreeBoxObject> mTree; // will be null if no tree bound
nsCOMPtr<nsITreeSelection> mSelection; // may be null
void RecursiveApplyTreeState(
nsCOMArray<nsNavHistoryResultNode>& aList,
const nsDataHashtable<nsStringHashKey, int>& aExpanded);
void RecursiveExpandCollapse(nsCOMArray<nsNavHistoryResultNode>& aList,
PRBool aExpand);
// This list is maintained only when a tree is attached (mTree != null) to
// the result. It is used to map rows to nodes.
typedef nsTArray< nsCOMPtr<nsNavHistoryResultNode> > VisibleList;
VisibleList mVisibleElements;
nsresult BuildVisibleList();
nsresult BuildVisibleSection(nsNavHistoryContainerResultNode* aContainer,
VisibleList* aVisible,
PRUint32 aVisibleStartIndex);
PRUint32 CountVisibleRowsForItem(nsNavHistoryResultNode* aNode);
enum ColumnType { Column_Unknown = -1, Column_Title, Column_URL, Column_Date, Column_VisitCount };
// node observers
PRBool mIsHistoryObserver;
PRBool mIsBookmarksObserver;
nsTArray<nsNavHistoryQueryResultNode*> mEverythingObservers;
typedef nsTArray<nsNavHistoryFolderResultNode*> FolderObserverList;
nsDataHashtable<nsTrimInt64HashKey, FolderObserverList* > mBookmarkObservers;
FolderObserverList* BookmarkObserversForId(PRInt64 aFolderId, PRBool aCreate);
// external observers
nsMaybeWeakPtrArray<nsINavHistoryResultViewObserver> mObservers;
// columns
enum ColumnType { Column_Unknown = -1, Column_Title, Column_URI, Column_Date,
Column_VisitCount };
ColumnType GetColumnType(nsITreeColumn* col);
ColumnType SortTypeToColumnType(PRUint32 aSortType,
PRBool* aDescending = nsnull);
PR_STATIC_CALLBACK(int) SortComparison_TitleLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_TitleGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_DateLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_DateGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_URLLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_URLGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_VisitCountLess(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
PR_STATIC_CALLBACK(int) SortComparison_VisitCountGreater(
nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure);
void SetTreeSortingIndicator();
void RecursiveExpandCollapse(nsNavHistoryContainerResultNode* aContainer,
PRBool aExpand);
void InvalidateTree();
nsresult FormatFriendlyTime(PRTime aTime, nsAString& aResult);
// Notify the result that a row has been added at index aIndex relative
// to aParent.
void RowAdded(PRInt32 aVisibleIndex, nsNavHistoryResultNode* aNode);
// Notify the result that the row with visible index aVisibleIndex has been
// removed from the tree.
void RowsRemoved(PRInt32 aVisibleIndex, PRUint32 aCount = 1);
// Notify the result that the contents of the row at visible index
// aVisibleIndex has been modified.
void RowChanged(PRInt32 aVisibleIndex);
void RowReplaced(PRInt32 aVisibleIndex, nsNavHistoryResultNode* aNode);
};
#endif // nsNavHistoryResult_h_