зеркало из https://github.com/mozilla/pjs.git
Add support for bookmark separators (bug 320261). r=brettw, ben.
This commit is contained in:
Родитель
98077997b9
Коммит
454c461160
|
@ -61,7 +61,8 @@
|
|||
<command id="placesCmd_new:folder"
|
||||
label="&cmd.new_folder.label;" accesskey="&cmd.new_folder.accesskey;"
|
||||
oncommand="PlacesController.newFolder()"/>
|
||||
<command id="placesCmd_new:separator" label="&cmd.new_separator.label;" accesskey="&cmd.new_separator.accesskey;"/>
|
||||
<command id="placesCmd_new:separator" label="&cmd.new_separator.label;" accesskey="&cmd.new_separator.accesskey;"
|
||||
oncommand="PlacesController.newSeparator()"/>
|
||||
</commandset>
|
||||
<commandset type="container|feed" readonly="true">
|
||||
<command id="placesCmd_reload" label="&cmd.reload.label;" accesskey="&cmd.reload.accesskey;"/>
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
selection="link|links|folder"/>
|
||||
<menuitem id="placesContext_new:folder" command="placesCmd_new:folder"
|
||||
selection="mutable"/>
|
||||
<menuitem id="placesContext_new:separator" command="placesCmd_new:separator"
|
||||
selection="mutable"/>
|
||||
<menuseparator id="placesContext_newSeparator"
|
||||
selection="mutable"/>
|
||||
<menuitem id="placesContext_edit:cut" command="placesCmd_edit:cut"
|
||||
|
|
|
@ -86,7 +86,9 @@ const SELECTION_IS_MOVABLE = 0x40;
|
|||
|
||||
// Place entries that are containers, e.g. bookmark folders or queries.
|
||||
const TYPE_X_MOZ_PLACE_CONTAINER = "text/x-moz-place-container";
|
||||
// Place entries that are not containers
|
||||
// Place entries that are bookmark separators.
|
||||
const TYPE_X_MOZ_PLACE_SEPARATOR = "text/x-moz-place-separator";
|
||||
// Place entries that are not containers or separators
|
||||
const TYPE_X_MOZ_PLACE = "text/x-moz-place";
|
||||
// Place entries in shortcut url format (url\ntitle)
|
||||
const TYPE_X_MOZ_URL = "text/x-moz-url";
|
||||
|
@ -145,8 +147,9 @@ function ViewConfig(dropTypes, dropOnTypes, excludeItems, expandQueries, firstDr
|
|||
this.firstDropIndex = firstDropIndex;
|
||||
this.filterTransactions = filterTransactions;
|
||||
}
|
||||
ViewConfig.GENERIC_DROP_TYPES = [TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE,
|
||||
TYPE_X_MOZ_URL];
|
||||
ViewConfig.GENERIC_DROP_TYPES = [TYPE_X_MOZ_PLACE_CONTAINER,
|
||||
TYPE_X_MOZ_PLACE_SEPARATOR, TYPE_X_MOZ_PLACE,
|
||||
TYPE_X_MOZ_URL]
|
||||
|
||||
/**
|
||||
* Manages grouping options for a particular view type.
|
||||
|
@ -283,7 +286,7 @@ var PlacesController = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Generates a HistoryResult for the contents of a folder.
|
||||
* Generates a HistoryResultNode for the contents of a folder.
|
||||
* @param folderId
|
||||
* The folder to open
|
||||
* @param excludeItems
|
||||
|
@ -293,7 +296,7 @@ var PlacesController = {
|
|||
* 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.
|
||||
* @returns A HistoryResultNode containing the contents of the folder.
|
||||
*/
|
||||
getFolderContents: function PC_getFolderContents(folderId, excludeItems, expandQueries) {
|
||||
var query = this._hist.getNewQuery();
|
||||
|
@ -463,6 +466,16 @@ var PlacesController = {
|
|||
return (node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines whether or not a ResultNode is a Bookmark separator.
|
||||
* @param node
|
||||
* A NavHistoryResultNode
|
||||
* @returns true if the node is a Bookmark separator, false otherwise
|
||||
*/
|
||||
nodeIsSeparator: function PC_nodeIsSeparator(node) {
|
||||
return (node.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines whether or not a ResultNode is a URL item or not
|
||||
* @param node
|
||||
|
@ -570,8 +583,7 @@ var PlacesController = {
|
|||
// New Folder
|
||||
this._setEnabled("placesCmd_new:folder", viewIsFolder);
|
||||
// New Separator
|
||||
// ...
|
||||
this._setEnabled("placesCmd_new:separator", false);
|
||||
this._setEnabled("placesCmd_new:separator", viewIsFolder);
|
||||
// Feed Reload
|
||||
this._setEnabled("placesCmd_reload", false);
|
||||
},
|
||||
|
@ -843,7 +855,17 @@ var PlacesController = {
|
|||
view.restoreSelection();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Bookmark separator somewhere.
|
||||
*/
|
||||
newSeparator: function PC_newSeparator() {
|
||||
var ip = this._activeView.insertionPoint;
|
||||
var txn = new PlacesInsertSeparatorTransaction(ip.folderId, ip.index);
|
||||
this.tm.doTransaction(txn);
|
||||
this._activeView.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a set of transactions for the removal of a range of items. A range is
|
||||
* an array of adjacent nodes in a view.
|
||||
|
@ -864,6 +886,11 @@ var PlacesController = {
|
|||
transactions.push(new PlacesRemoveFolderTransaction(
|
||||
asFolder(node).folderId, asFolder(node.parent).folderId, index));
|
||||
}
|
||||
else if (this.nodeIsSeparator(node)) {
|
||||
// A Bookmark separator.
|
||||
transactions.push(new PlacesRemoveSeparatorTransaction(
|
||||
asFolder(node.parent).folderId, index));
|
||||
}
|
||||
else if (this.nodeIsFolder(node.parent)) {
|
||||
// A Bookmark in a Bookmark Folder.
|
||||
transactions.push(new PlacesRemoveItemTransaction(
|
||||
|
@ -956,6 +983,7 @@ var PlacesController = {
|
|||
switch (type) {
|
||||
case TYPE_X_MOZ_PLACE_CONTAINER:
|
||||
case TYPE_X_MOZ_PLACE:
|
||||
case TYPE_X_MOZ_PLACE_SEPARATOR:
|
||||
var wrapped = "";
|
||||
if (this.nodeIsFolder(node))
|
||||
wrapped += asFolder(node).folderId + "\n";
|
||||
|
@ -1000,6 +1028,7 @@ var PlacesController = {
|
|||
switch (type) {
|
||||
case TYPE_X_MOZ_PLACE_CONTAINER:
|
||||
case TYPE_X_MOZ_PLACE:
|
||||
case TYPE_X_MOZ_PLACE_SEPARATOR:
|
||||
nodes.push({ folderId: parseInt(parts[i++]),
|
||||
uri: parts[i] ? this._uri(parts[i]) : null,
|
||||
parent: parseInt(parts[++i]),
|
||||
|
@ -1111,6 +1140,19 @@ var PlacesController = {
|
|||
return new PlacesMoveItemTransaction(data.uri, data.parent,
|
||||
data.index, container,
|
||||
index);
|
||||
case TYPE_X_MOZ_PLACE_SEPARATOR:
|
||||
if (copy) {
|
||||
// There is no data in a separator, so copying it just amounts to
|
||||
// inserting a new separator.
|
||||
return new PlacesInsertSeparatorTransaction(container, index);
|
||||
}
|
||||
// Similarly, moving a separator is just removing the old one and
|
||||
// then creating a new one.
|
||||
var removeTxn =
|
||||
new PlacesRemoveSeparatorTransaction(data.parent, data.index);
|
||||
var createTxn =
|
||||
new PlacesInsertSeparatorTransaction(container, index);
|
||||
return new PlacesAggregateTransaction("SeparatorMove", [removeTxn, createTxn]);
|
||||
case TYPE_X_MOZ_URL:
|
||||
// Creating and Setting the title is a two step process, so create
|
||||
// a transaction for each then aggregate them.
|
||||
|
@ -1170,6 +1212,9 @@ var PlacesController = {
|
|||
|
||||
addData(TYPE_X_MOZ_PLACE_CONTAINER);
|
||||
}
|
||||
else if (this.nodeIsSeparator(node)) {
|
||||
addData(TYPE_X_MOZ_PLACE_SEPARATOR);
|
||||
}
|
||||
else {
|
||||
// This order is _important_! It controls how this and other
|
||||
// applications select data to be inserted based on type.
|
||||
|
@ -1193,7 +1238,7 @@ var PlacesController = {
|
|||
Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
var foundFolder = false, foundLink = false;
|
||||
var pcString = placeString = mozURLString = htmlString = unicodeString = "";
|
||||
var pcString = psString = placeString = mozURLString = htmlString = unicodeString = "";
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var node = nodes[i];
|
||||
var self = this;
|
||||
|
@ -1203,6 +1248,9 @@ var PlacesController = {
|
|||
}
|
||||
if (this.nodeIsFolder(node) || this.nodeIsQuery(node))
|
||||
pcString += generateChunk(TYPE_X_MOZ_PLACE_CONTAINER);
|
||||
else if (this.nodeIsSeparator(node)) {
|
||||
psString += generateChunk(TYPE_X_MOZ_PLACE_SEPARATOR);
|
||||
}
|
||||
else {
|
||||
placeString += generateChunk(TYPE_X_MOZ_PLACE);
|
||||
mozURLString += generateChunk(TYPE_X_MOZ_URL);
|
||||
|
@ -1220,6 +1268,8 @@ var PlacesController = {
|
|||
// select data to be inserted based on type.
|
||||
if (pcString)
|
||||
addData(TYPE_X_MOZ_PLACE_CONTAINER, pcString);
|
||||
if (psString)
|
||||
addData(TYPE_X_MOZ_PLACE_SEPARATOR, psString);
|
||||
if (placeString)
|
||||
addData(TYPE_X_MOZ_PLACE, placeString);
|
||||
if (unicodeString)
|
||||
|
@ -1229,7 +1279,7 @@ var PlacesController = {
|
|||
if (mozURLString)
|
||||
addData(TYPE_X_MOZ_URL, mozURLString);
|
||||
|
||||
if (pcString || placeString || unicodeString || htmlString ||
|
||||
if (pcString || psString || placeString || unicodeString || htmlString ||
|
||||
mozURLString) {
|
||||
var clipboard =
|
||||
Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard);
|
||||
|
@ -1253,6 +1303,7 @@ var PlacesController = {
|
|||
Cc["@mozilla.org/widget/transferable;1"].
|
||||
createInstance(Ci.nsITransferable);
|
||||
xferable.addDataFlavor(TYPE_X_MOZ_PLACE_CONTAINER);
|
||||
xferable.addDataFlavor(TYPE_X_MOZ_PLACE_SEPARATOR);
|
||||
xferable.addDataFlavor(TYPE_X_MOZ_PLACE);
|
||||
xferable.addDataFlavor(TYPE_X_MOZ_URL);
|
||||
xferable.addDataFlavor(TYPE_UNICODE);
|
||||
|
@ -1496,6 +1547,28 @@ PlacesCreateItemTransaction.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new Separator
|
||||
*/
|
||||
function PlacesInsertSeparatorTransaction(container, index) {
|
||||
this._container = container;
|
||||
this._index = index;
|
||||
this._id = null;
|
||||
}
|
||||
PlacesInsertSeparatorTransaction.prototype = {
|
||||
__proto__: PlacesBaseTransaction.prototype,
|
||||
|
||||
doTransaction: function PIST_doTransaction() {
|
||||
LOG("Create separator in: " + this._container + "," + this._index);
|
||||
this._id = this._bms.insertSeparator(this._container, this._index);
|
||||
},
|
||||
|
||||
undoTransaction: function PIST_undoTransaction() {
|
||||
LOG("UNCreate separator from: " + this._container + "," + this._index);
|
||||
this._bms.removeChildAt(this._container, this._index);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Move a Folder
|
||||
*/
|
||||
|
@ -1686,6 +1759,27 @@ PlacesRemoveItemTransaction.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a separator
|
||||
*/
|
||||
function PlacesRemoveSeparatorTransaction(oldContainer, oldIndex) {
|
||||
this._oldContainer = oldContainer;
|
||||
this._oldIndex = oldIndex;
|
||||
}
|
||||
PlacesRemoveSeparatorTransaction.prototype = {
|
||||
__proto__: PlacesBaseTransaction.prototype,
|
||||
|
||||
doTransaction: function PRST_doTransaction() {
|
||||
LOG("Remove Separator from: " + this._oldContainer + "," + this._oldIndex);
|
||||
this._bms.removeChildAt(this._oldContainer, this._oldIndex);
|
||||
},
|
||||
|
||||
undoTransaction: function PRST_undoTransaction() {
|
||||
LOG("UNRemove Separator from: " + this._oldContainer + "," + this._oldIndex);
|
||||
this._bms.insertSeparator(this._oldContainer, this._oldIndex);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Edit a Folder
|
||||
*/
|
||||
|
|
|
@ -206,11 +206,11 @@
|
|||
<field name="filterTransactions">false</field>
|
||||
|
||||
<field name="supportedDropTypes">
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE_SEPARATOR, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
</field>
|
||||
|
||||
<field name="supportedDropOnTypes">
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE_SEPARATOR, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
</field>
|
||||
|
||||
<method name="selectAll">
|
||||
|
|
|
@ -247,11 +247,11 @@
|
|||
<field name="filterTransactions">false</field>
|
||||
|
||||
<field name="supportedDropTypes">
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE_SEPARATOR, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
</field>
|
||||
|
||||
<field name="supportedDropOnTypes">
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
[TYPE_X_MOZ_PLACE_CONTAINER, TYPE_X_MOZ_PLACE_SEPARATOR, TYPE_X_MOZ_PLACE, TYPE_X_MOZ_URL]
|
||||
</field>
|
||||
|
||||
<method name="selectAll">
|
||||
|
@ -316,6 +316,14 @@
|
|||
}
|
||||
setTimeout(hitch(this._self, this._self._rebuild), 1);
|
||||
},
|
||||
onSeparatorAdded: function TB_O_onSeparatorAdded(parent, index) {
|
||||
if (!this._numBatches)
|
||||
this._self.init();
|
||||
},
|
||||
onSeparatorRemoved: function TB_O_onSeparatorRemoved(parent, index) {
|
||||
if (!this._numBatches)
|
||||
this._self.init();
|
||||
}
|
||||
})]]></field>
|
||||
<field name="_DNDObserver"><![CDATA[({
|
||||
// XXXben ew.
|
||||
|
|
|
@ -433,16 +433,16 @@
|
|||
<parameter name="insertionPoint"/>
|
||||
<parameter name="excludeItems"/>
|
||||
<body><![CDATA[
|
||||
var result =
|
||||
var folder =
|
||||
PlacesController.getFolderContents(insertionPoint.folderId,
|
||||
excludeItems, false);
|
||||
var index = insertionPoint.index;
|
||||
if (insertionPoint.index == 0)
|
||||
index = 0;
|
||||
else if (insertionPoint.index == -1 || insertionPoint.index >= result.root.childCount)
|
||||
index = result.root.childCount - 1;
|
||||
ASSERT(index < result.childCount, "index out of range: " + index + " > " + result);
|
||||
return index > -1 ? result.root.getChild(index) : null;
|
||||
else if (insertionPoint.index == -1 || insertionPoint.index >= folder.childCount)
|
||||
index = folder.childCount - 1;
|
||||
ASSERT(index < folder.childCount, "index out of range: " + index + " > " + folder);
|
||||
return index > -1 ? folder.getChild(index) : null;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
|
|
@ -162,6 +162,20 @@ interface nsINavBookmarkObserver : nsISupports
|
|||
* @param property The property that was changed.
|
||||
*/
|
||||
void onFolderChanged(in PRInt64 folder, in ACString property);
|
||||
|
||||
/**
|
||||
* Notify this observer that a separator has been added.
|
||||
* @param parent The id of the separator's parent.
|
||||
* @param index The separator's index inside its parent.
|
||||
*/
|
||||
void onSeparatorAdded(in PRInt64 parent, in PRInt32 index);
|
||||
|
||||
/**
|
||||
* Notify this observer that a separator has been removed.
|
||||
* @param parent The id of the separator's parent.
|
||||
* @param index The separator's old index in its parent.
|
||||
*/
|
||||
void onSeparatorRemoved(in PRInt64 parent, in PRInt32 index);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -263,6 +277,21 @@ interface nsINavBookmarksService : nsISupports
|
|||
*/
|
||||
PRInt64 getChildFolder(in PRInt64 folder, in AString subFolder);
|
||||
|
||||
/**
|
||||
* Inserts a bookmark separator into the given folder at the given index.
|
||||
* The separator can be removed using removeChildAt().
|
||||
* @param folder Parent folder of the separator
|
||||
* @param index The separator's index under folder, or -1 to append
|
||||
*/
|
||||
void insertSeparator(in PRInt64 folder, in PRInt32 index);
|
||||
|
||||
/**
|
||||
* Removes any type of child (item, folder, or separator) at the given index.
|
||||
* @param folder The folder to remove a child from
|
||||
* @param index The index of the child to remove
|
||||
*/
|
||||
void removeChildAt(in PRInt64 folder, in PRInt32 index);
|
||||
|
||||
/**
|
||||
* Set the history/bookmark title for a URI. The new title will be used
|
||||
* anywhere the URI is shown in bookmarks or history.
|
||||
|
|
|
@ -81,6 +81,7 @@ interface nsINavHistoryResultNode : nsISupports
|
|||
const PRUint32 RESULT_TYPE_REMOTE_CONTAINER = 4; // nsINavHistoryContainerResultNode
|
||||
const PRUint32 RESULT_TYPE_QUERY = 5; // nsINavHistoryQueryResultNode
|
||||
const PRUint32 RESULT_TYPE_FOLDER = 6; // nsINavHistoryFolderResultNode
|
||||
const PRUint32 RESULT_TYPE_SEPARATOR = 7; // nsINavHistoryResultNode
|
||||
readonly attribute PRUint32 type;
|
||||
|
||||
/**
|
||||
|
@ -814,10 +815,10 @@ interface nsINavHistoryQueryOptions : nsISupports
|
|||
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.
|
||||
* This option excludes all URIs and separators 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;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
-moz-appearance: listbox;
|
||||
}
|
||||
|
||||
treechildren::-moz-tree-image(title) {
|
||||
treechildren::-moz-tree-image(title, container) {
|
||||
padding-right: 2px;
|
||||
margin: 0px 2px;
|
||||
list-style-image: url("chrome://global/skin/icons/folder-item.png") !important;
|
||||
|
|
|
@ -272,6 +272,7 @@ protected:
|
|||
void HandleHeadEnd();
|
||||
void HandleLinkBegin(const nsIParserNode& node);
|
||||
void HandleLinkEnd();
|
||||
void HandleSeparator();
|
||||
|
||||
// This is a list of frames. We really want a recursive parser, but the HTML
|
||||
// parser gives us tags as a stream. This implements all the state on a stack
|
||||
|
@ -410,9 +411,16 @@ BookmarkContentSink::CloseContainer(const nsHTMLTag aTag)
|
|||
NS_IMETHODIMP
|
||||
BookmarkContentSink::AddLeaf(const nsIParserNode& aNode)
|
||||
{
|
||||
// save any text we find
|
||||
if (aNode.GetNodeType() == eHTMLTag_text) {
|
||||
CurFrame().mPreviousText += aNode.GetText();
|
||||
switch (aNode.GetNodeType()) {
|
||||
case eHTMLTag_text:
|
||||
// save any text we find
|
||||
if (aNode.GetNodeType() == eHTMLTag_text) {
|
||||
CurFrame().mPreviousText += aNode.GetText();
|
||||
}
|
||||
break;
|
||||
case eHTMLTag_hr:
|
||||
HandleSeparator();
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -640,6 +648,24 @@ BookmarkContentSink::HandleLinkEnd()
|
|||
}
|
||||
|
||||
|
||||
// BookmarkContentSink::HandleSeparator
|
||||
//
|
||||
// Inserts a separator into the current container
|
||||
void
|
||||
BookmarkContentSink::HandleSeparator()
|
||||
{
|
||||
BookmarkImportFrame& frame = CurFrame();
|
||||
|
||||
// bookmarks.html contains a separator between the toolbar menu and the
|
||||
// rest of the items. Since we pull the toolbar menu out into the top level,
|
||||
// we want to skip over this separator since it looks out of place.
|
||||
if (frame.mLastContainerType != BookmarkImportFrame::Container_Toolbar) {
|
||||
// create the separator
|
||||
mBookmarksService->InsertSeparator(frame.mContainerID, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BookmarkContentSink::NewFrame
|
||||
//
|
||||
// This is called when there is a new folder found. The folder takes the
|
||||
|
|
|
@ -189,12 +189,26 @@ nsNavBookmarks::Init()
|
|||
"JOIN moz_bookmarks_folders c ON c.id = a.folder_child "
|
||||
"WHERE a.parent = ?1 AND a.position >= ?2 AND a.position <= ?3");
|
||||
|
||||
// Construct a result where the first columns are padded out to the width
|
||||
// of mDBGetVisitPageInfo, containing additional columns for position,
|
||||
// item_child, and folder_child from moz_bookmarks. This selects only
|
||||
// _separator_ children which are in moz_bookmarks. Results are
|
||||
// kGetInfoIndex_* kGetChildrenIndex_*. item_child and folder_child will
|
||||
// be NULL for separators.
|
||||
NS_NAMED_LITERAL_CSTRING(selectSeparatorChildren,
|
||||
"SELECT null, null, null, null, null, null, null, null, null, a.position, null, null, null "
|
||||
"FROM moz_bookmarks a "
|
||||
"WHERE a.parent = ?1 AND a.position >= ?2 AND a.position <= ?3 AND "
|
||||
"a.item_child ISNULL and a.folder_child ISNULL");
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(orderByPosition, " ORDER BY a.position");
|
||||
|
||||
// mDBGetChildren: select all children of a given folder, sorted by position
|
||||
rv = dbConn->CreateStatement(selectItemChildren +
|
||||
NS_LITERAL_CSTRING(" UNION ALL ") +
|
||||
selectFolderChildren + orderByPosition,
|
||||
selectFolderChildren +
|
||||
NS_LITERAL_CSTRING(" UNION ALL ") +
|
||||
selectSeparatorChildren + orderByPosition,
|
||||
getter_AddRefs(mDBGetChildren));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -212,6 +226,10 @@ nsNavBookmarks::Init()
|
|||
getter_AddRefs(mDBIndexOfFolder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("SELECT item_child, folder_child FROM moz_bookmarks WHERE parent = ?1 AND position = ?2"),
|
||||
getter_AddRefs(mDBGetChildAt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = InitRoots();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -446,7 +464,7 @@ nsNavBookmarks::AdjustIndices(PRInt64 aFolder,
|
|||
if (item->itemURI) {
|
||||
nsIURI *uri = item->itemURI;
|
||||
obs->OnItemMoved(uri, aFolder, oldPosition, newPosition);
|
||||
} else {
|
||||
} else if (item->folderChild) {
|
||||
obs->OnFolderMoved(item->folderChild, aFolder, oldPosition,
|
||||
aFolder, newPosition);
|
||||
}
|
||||
|
@ -709,6 +727,135 @@ nsNavBookmarks::CreateContainer(PRInt64 aParent, const nsAString &aName,
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::InsertSeparator(PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
|
||||
PRInt32 index = (aIndex == -1) ? FolderCount(aParent) : aIndex;
|
||||
|
||||
nsresult rv = AdjustIndices(aParent, index, PR_INT32_MAX, 1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks "
|
||||
"(parent, position) VALUES (?1,?2)"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->BindInt64Parameter(0, aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt32Parameter(1, index);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
|
||||
OnSeparatorAdded(aParent, index))
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::RemoveChildAt(PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
mozIStorageConnection *dbConn = DBConn();
|
||||
mozStorageTransaction transaction(dbConn, PR_FALSE);
|
||||
nsresult rv;
|
||||
PRInt64 item, folder;
|
||||
|
||||
{
|
||||
mozStorageStatementScoper scope(mDBGetChildAt);
|
||||
rv = mDBGetChildAt->BindInt64Parameter(0, aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = mDBGetChildAt->BindInt32Parameter(1, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasMore;
|
||||
rv = mDBGetChildAt->ExecuteStep(&hasMore);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!hasMore) {
|
||||
// Child doesn't exist
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (mDBGetChildAt->IsNull(0)) {
|
||||
item = 0;
|
||||
folder = mDBGetChildAt->AsInt64(1);
|
||||
} else {
|
||||
folder = 0;
|
||||
item = mDBGetChildAt->AsInt64(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (item != 0) {
|
||||
// We're removing an item, go find its URI.
|
||||
mozIStorageStatement *pageInfo = History()->DBGetIdPageInfo();
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
{
|
||||
mozStorageStatementScoper scope(pageInfo);
|
||||
rv = pageInfo->BindInt64Parameter(0, item);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasMore;
|
||||
rv = pageInfo->ExecuteStep(&hasMore);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!hasMore) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsCAutoString spec;
|
||||
rv = pageInfo->GetUTF8String(1, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewURI(getter_AddRefs(uri), spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Commit this transaction so that we don't notify observers mid-tranaction
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return RemoveItem(aParent, uri);
|
||||
}
|
||||
if (folder != 0) {
|
||||
// Commit this transaction so that we don't notify observers mid-tranaction
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return RemoveFolder(folder);
|
||||
}
|
||||
|
||||
// No item or folder, so this is a separator.
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("DELETE FROM moz_bookmarks WHERE parent = ?1 AND position = ?2"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->BindInt64Parameter(0, aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt32Parameter(1, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AdjustIndices(aParent, aIndex + 1, PR_INT32_MAX, -1);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
|
||||
OnSeparatorRemoved(aParent, aIndex))
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavBookmarks::RemoveFolder(PRInt64 aFolder)
|
||||
{
|
||||
|
@ -785,6 +932,7 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolder)
|
|||
{
|
||||
mozStorageTransaction transaction(DBConn(), PR_FALSE);
|
||||
|
||||
nsTArray<PRInt32> separatorChildren; // separator indices
|
||||
nsTArray<PRInt64> folderChildren;
|
||||
nsCOMArray<nsIURI> itemChildren;
|
||||
nsresult rv;
|
||||
|
@ -805,6 +953,9 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolder)
|
|||
// folder
|
||||
folderChildren.AppendElement(
|
||||
mDBGetChildren->AsInt64(kGetChildrenIndex_FolderChild));
|
||||
} else if (mDBGetChildren->IsNull(kGetChildrenIndex_ItemChild)) {
|
||||
// separator
|
||||
separatorChildren.AppendElement(mDBGetChildren->AsInt32(kGetChildrenIndex_Position));
|
||||
} else {
|
||||
// item (URI)
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
|
@ -818,8 +969,16 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolder)
|
|||
}
|
||||
}
|
||||
|
||||
// remove folders
|
||||
// Remove separators. The list of separators will already be sorted since
|
||||
// we order by position, so by enumerating it backwards, we avoid having to
|
||||
// deal with shifting indices.
|
||||
PRUint32 i;
|
||||
for (i = separatorChildren.Length() - 1; i != PRUint32(-1); --i) {
|
||||
rv = RemoveChildAt(aFolder, separatorChildren[i]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// remove folders
|
||||
for (i = 0; i < folderChildren.Length(); ++i) {
|
||||
rv = RemoveFolder(folderChildren[i]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1201,6 +1360,13 @@ nsNavBookmarks::QueryFolderChildren(PRInt64 aFolderId,
|
|||
rv = ResultNodeForFolder(folder, aOptions, getter_AddRefs(node));
|
||||
if (NS_FAILED(rv))
|
||||
continue;
|
||||
} else if (mDBGetChildren->IsNull(kGetChildrenIndex_ItemChild)) {
|
||||
// separator
|
||||
if (aOptions->ExcludeItems()) {
|
||||
continue;
|
||||
}
|
||||
node = new nsNavHistorySeparatorResultNode();
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY);
|
||||
} else {
|
||||
rv = History()->RowToResult(mDBGetChildren, options,
|
||||
getter_AddRefs(node));
|
||||
|
|
|
@ -130,6 +130,7 @@ private:
|
|||
|
||||
nsCOMPtr<mozIStorageStatement> mDBIndexOfItem;
|
||||
nsCOMPtr<mozIStorageStatement> mDBIndexOfFolder;
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetChildAt;
|
||||
|
||||
nsCOMPtr<nsIStringBundle> mBundle;
|
||||
|
||||
|
|
|
@ -183,6 +183,7 @@ nsIAtom* nsNavHistory::sMenuRootAtom = nsnull;
|
|||
nsIAtom* nsNavHistory::sToolbarRootAtom = nsnull;
|
||||
nsIAtom* nsNavHistory::sSessionStartAtom = nsnull;
|
||||
nsIAtom* nsNavHistory::sSessionContinueAtom = nsnull;
|
||||
nsIAtom* nsNavHistory::sContainerAtom = nsnull;
|
||||
|
||||
nsNavHistory* nsNavHistory::gHistoryService;
|
||||
|
||||
|
@ -199,6 +200,7 @@ nsNavHistory::nsNavHistory() : mNowValid(PR_FALSE),
|
|||
sToolbarRootAtom = NS_NewAtom("toolbar-root");
|
||||
sSessionStartAtom = NS_NewAtom("session-start");
|
||||
sSessionContinueAtom = NS_NewAtom("session-continue");
|
||||
sContainerAtom = NS_NewAtom("container");
|
||||
}
|
||||
|
||||
|
||||
|
@ -219,6 +221,7 @@ nsNavHistory::~nsNavHistory()
|
|||
NS_IF_RELEASE(sToolbarRootAtom);
|
||||
NS_IF_RELEASE(sSessionStartAtom);
|
||||
NS_IF_RELEASE(sSessionContinueAtom);
|
||||
NS_IF_RELEASE(sContainerAtom);
|
||||
}
|
||||
|
||||
|
||||
|
@ -435,6 +438,13 @@ nsNavHistory::InitDB()
|
|||
getter_AddRefs(mDBGetURLPageInfoFull));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// mDBGetIdPageInfo
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, h.title, h.user_title, h.rev_host, h.visit_count "
|
||||
"FROM moz_history h WHERE h.id = ?1"),
|
||||
getter_AddRefs(mDBGetIdPageInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// mDBGetIdPageInfoFull
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, h.url, h.title, h.user_title, h.rev_host, h.visit_count, "
|
||||
|
|
|
@ -180,6 +180,9 @@ public:
|
|||
mozIStorageStatement* DBGetURLPageInfoFull()
|
||||
{ return mDBGetURLPageInfoFull; }
|
||||
|
||||
// select a history row by id
|
||||
mozIStorageStatement* DBGetIdPageInfo() { return mDBGetIdPageInfo; }
|
||||
|
||||
// select a history row by id, with visit date info (extra work)
|
||||
mozIStorageStatement* DBGetIdPageInfoFull()
|
||||
{ return mDBGetIdPageInfoFull; }
|
||||
|
@ -196,6 +199,7 @@ public:
|
|||
static nsIAtom* sToolbarRootAtom;
|
||||
static nsIAtom* sSessionStartAtom;
|
||||
static nsIAtom* sSessionContinueAtom;
|
||||
static nsIAtom* sContainerAtom;
|
||||
|
||||
// this actually executes a query and gives you results, it is used by
|
||||
// nsNavHistoryQueryResultNode
|
||||
|
@ -282,6 +286,7 @@ protected:
|
|||
//nsCOMPtr<mozIStorageStatement> mDBGetVisitPageInfo; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetURLPageInfo; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetURLPageInfoFull; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetIdPageInfo; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetIdPageInfoFull; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBFullAutoComplete; // kAutoCompleteIndex_* results, 1 arg (max # results)
|
||||
static const PRInt32 kAutoCompleteIndex_URL;
|
||||
|
|
|
@ -553,9 +553,8 @@ nsNavHistoryContainerResultNode::GetSortingComparator(PRUint32 aSortType)
|
|||
|
||||
// nsNavHistoryContainerResultNode::RecursiveSort
|
||||
//
|
||||
// This is used by Result::SortAll and it is static so it can also be used
|
||||
// by nsNavHistory::GetQueryResults to sort node arrays without having a
|
||||
// root container.
|
||||
// This is used by Result::SortAll and QueryResultNode::FillChildren to sort
|
||||
// the child list.
|
||||
//
|
||||
// This does NOT update any visibility or tree information. The caller will
|
||||
// have to completely rebuild the visible list after this.
|
||||
|
@ -2307,7 +2306,17 @@ nsNavHistoryQueryResultNode::OnFolderChanged(PRInt64 aFolder,
|
|||
return Refresh();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryResultNode::OnSeparatorAdded(PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryResultNode::OnSeparatorRemoved(PRInt64 aParent,
|
||||
PRInt32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsNavHistoryFolderResultNode ************************************************
|
||||
//
|
||||
|
@ -2959,6 +2968,87 @@ nsNavHistoryFolderResultNode::OnFolderChanged(PRInt64 aFolder,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsNavHistoryFolderResultNode::OnSeparatorAdded (nsINavBookmarkObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryFolderResultNode::OnSeparatorAdded(PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
NS_ASSERTION(aParent == mFolderId, "Got wrong bookmark update");
|
||||
if (! StartIncrementalUpdate())
|
||||
return NS_OK;
|
||||
|
||||
// We remove all separators if the folder view is sorted, so only
|
||||
// bother updating if there is no sort in effect.
|
||||
if (GetSortType() != nsINavHistoryQueryOptions::SORT_BY_NONE) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsNavHistoryResultNode* node = new nsNavHistorySeparatorResultNode();
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return InsertChildAt(node, aIndex);
|
||||
}
|
||||
|
||||
// nsNavHistoryFolderResultNode::OnSeparatorRemoved (nsINavBookmarkObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryFolderResultNode::OnSeparatorRemoved(PRInt64 aParent,
|
||||
PRInt32 aIndex)
|
||||
{
|
||||
NS_ASSERTION(aParent == mFolderId, "Got wrong bookmark update");
|
||||
if (! StartIncrementalUpdate())
|
||||
return NS_OK;
|
||||
|
||||
// We remove all separators if the folder view is sorted, so only
|
||||
// bother updating if there is no sort in effect.
|
||||
if (GetSortType() != nsINavHistoryQueryOptions::SORT_BY_NONE) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aIndex >= mChildren.Count()) {
|
||||
NS_NOTREACHED("Removing separator at invalid index");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mChildren[aIndex]->IsSeparator()) {
|
||||
NS_NOTREACHED("OnSeparatorRemoved called for a non-separator node");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return RemoveChildAt(aIndex);
|
||||
}
|
||||
|
||||
// nsNavHistoryFolderResultNode::RecursiveSort
|
||||
|
||||
void
|
||||
nsNavHistoryFolderResultNode::RecursiveSort(
|
||||
nsICollation* aCollation, SortComparator aComparator)
|
||||
{
|
||||
if (GetSortType() != nsINavHistoryQueryOptions::SORT_BY_NONE) {
|
||||
// We weren't sorted before, but now we are.
|
||||
// Remove any separators so that they don't appear in the sorted list.
|
||||
|
||||
for (PRUint32 i = mChildren.Count() - 1; i != PRUint32(-1); --i) {
|
||||
if (mChildren[i]->IsSeparator()) {
|
||||
mChildren.RemoveObjectAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsNavHistoryContainerResultNode::RecursiveSort(aCollation, aComparator);
|
||||
}
|
||||
|
||||
// nsNavHistorySeparatorResultNode
|
||||
//
|
||||
// Separator nodes do not hold any data
|
||||
|
||||
nsNavHistorySeparatorResultNode::nsNavHistorySeparatorResultNode()
|
||||
: nsNavHistoryResultNode(EmptyCString(), 0, 0, EmptyCString())
|
||||
{
|
||||
}
|
||||
|
||||
// nsNavHistoryResult **********************************************************
|
||||
|
||||
|
@ -3788,9 +3878,16 @@ NS_IMETHODIMP nsNavHistoryResult::GetRowProperties(PRInt32 row,
|
|||
if (row < 0 || row >= PRInt32(mVisibleElements.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsNavHistoryResultNode *node = mVisibleElements[row];
|
||||
|
||||
// Add the container property if it's applicable for this row.
|
||||
if (node->IsContainer()) {
|
||||
properties->AppendElement(nsNavHistory::sContainerAtom);
|
||||
}
|
||||
|
||||
// Next handle properties for session information.
|
||||
if (! mShowSessions)
|
||||
return NS_OK; // don't need to bother to compute session boundaries
|
||||
nsNavHistoryResultNode *node = mVisibleElements[row];
|
||||
if (! node->IsVisit())
|
||||
return NS_OK; // not a visit, so there are no sessions
|
||||
|
||||
|
@ -3909,13 +4006,13 @@ NS_IMETHODIMP nsNavHistoryResult::IsContainerEmpty(PRInt32 row, PRBool *_retval)
|
|||
|
||||
|
||||
// nsNavHistoryResult::IsSeparator (nsITreeView)
|
||||
//
|
||||
// We don't support separators
|
||||
// FIXME: do bookmark separators
|
||||
|
||||
NS_IMETHODIMP nsNavHistoryResult::IsSeparator(PRInt32 row, PRBool *_retval)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
if (row < 0 || row >= PRInt32(mVisibleElements.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
*_retval = mVisibleElements[row]->IsSeparator();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4022,7 +4119,9 @@ NS_IMETHODIMP nsNavHistoryResult::GetImageSrc(PRInt32 row, nsITreeColumn *col,
|
|||
|
||||
// Containers may or may not have favicons. If not, we will return nothing
|
||||
// as the image, and the style rule should pick up the default.
|
||||
if (node->IsContainer() && node->mFaviconURI.IsEmpty()) {
|
||||
// Separator rows never have icons.
|
||||
if (node->IsSeparator() ||
|
||||
(node->IsContainer() && node->mFaviconURI.IsEmpty())) {
|
||||
_retval.Truncate(0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -4079,7 +4178,9 @@ NS_IMETHODIMP nsNavHistoryResult::GetCellText(PRInt32 row,
|
|||
// items in the tree view so return a special string if the title is
|
||||
// empty. Do it here so that callers can still get at the 0 length title
|
||||
// if they go through the "result" API.
|
||||
if (! node->mTitle.IsEmpty()) {
|
||||
if (node->IsSeparator()) {
|
||||
_retval.Truncate(0);
|
||||
} else if (! node->mTitle.IsEmpty()) {
|
||||
_retval = NS_ConvertUTF8toUTF16(node->mTitle);
|
||||
} else {
|
||||
nsXPIDLString value;
|
||||
|
@ -4114,7 +4215,11 @@ NS_IMETHODIMP nsNavHistoryResult::GetCellText(PRInt32 row,
|
|||
}
|
||||
case Column_VisitCount:
|
||||
{
|
||||
_retval = NS_ConvertUTF8toUTF16(nsPrintfCString("%d", node->mAccessCount));
|
||||
if (node->IsSeparator()) {
|
||||
_retval.Truncate(0);
|
||||
} else {
|
||||
_retval = NS_ConvertUTF8toUTF16(nsPrintfCString("%d", node->mAccessCount));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -4706,6 +4811,30 @@ nsNavHistoryResult::OnFolderChanged(PRInt64 aFolder,
|
|||
}
|
||||
|
||||
|
||||
// nsNavHistoryResult::OnSeparatorAdded (nsINavBookmarkObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResult::OnSeparatorAdded(PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
// Separators only appear in folder nodes, so history observers don't care.
|
||||
ENUMERATE_BOOKMARK_OBSERVERS_FOR_FOLDER(aParent,
|
||||
OnSeparatorAdded(aParent, aIndex));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavHistoryResult::OnSeparatorRemoved (nsINavBookmarkObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResult::OnSeparatorRemoved(PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
// Separators only appear in folder nodes, so history observers don't care.
|
||||
ENUMERATE_BOOKMARK_OBSERVERS_FOR_FOLDER(aParent,
|
||||
OnSeparatorRemoved(aParent, aIndex));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavHistoryResult::OnVisit (nsINavHistoryObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -239,7 +239,11 @@ public:
|
|||
GetType(&type);
|
||||
return IsTypeQuery(type);
|
||||
}
|
||||
|
||||
PRBool IsSeparator() {
|
||||
PRUint32 type;
|
||||
GetType(&type);
|
||||
return (type == nsINavHistoryResultNode::RESULT_TYPE_SEPARATOR);
|
||||
}
|
||||
nsNavHistoryContainerResultNode* GetAsContainer() {
|
||||
NS_ASSERTION(IsContainer(), "Not a container");
|
||||
return NS_REINTERPRET_CAST(nsNavHistoryContainerResultNode*, this);
|
||||
|
@ -431,7 +435,8 @@ public:
|
|||
typedef nsCOMArray<nsNavHistoryResultNode>::nsCOMArrayComparatorFunc SortComparator;
|
||||
virtual PRUint32 GetSortType();
|
||||
static SortComparator GetSortingComparator(PRUint32 aSortType);
|
||||
void RecursiveSort(nsICollation* aCollation, SortComparator aComparator);
|
||||
virtual void RecursiveSort(nsICollation* aCollation,
|
||||
SortComparator aComparator);
|
||||
PRUint32 FindInsertionPoint(nsNavHistoryResultNode* aNode, SortComparator aComparator);
|
||||
PRBool DoesChildNeedResorting(PRUint32 aIndex, SortComparator aComparator);
|
||||
|
||||
|
@ -589,6 +594,10 @@ public:
|
|||
|
||||
virtual void OnRemoving();
|
||||
|
||||
// Override the sorting implementation to remove separators if we are sorted.
|
||||
virtual void RecursiveSort(nsICollation* aCollation,
|
||||
SortComparator aComparator);
|
||||
|
||||
public:
|
||||
|
||||
// this indicates whether the folder contents are valid, they don't go away
|
||||
|
@ -604,6 +613,17 @@ public:
|
|||
PRBool StartIncrementalUpdate();
|
||||
};
|
||||
|
||||
// nsNavHistorySeparatorResultNode
|
||||
//
|
||||
// Separator result nodes do not hold any data.
|
||||
class nsNavHistorySeparatorResultNode : public nsNavHistoryResultNode
|
||||
{
|
||||
public:
|
||||
nsNavHistorySeparatorResultNode();
|
||||
|
||||
NS_IMETHOD GetType(PRUint32* type)
|
||||
{ *type = nsNavHistoryResultNode::RESULT_TYPE_SEPARATOR; return NS_OK; }
|
||||
};
|
||||
|
||||
// nsNavHistoryResult
|
||||
//
|
||||
|
|
Загрузка…
Ссылка в новой задаче