зеркало из https://github.com/mozilla/pjs.git
Make bookmark and history views update dynamically (bug 317826 and 317827), r=brettw.
Original committer: bryner%brianryner.com Original revision: 1.16 Original date: 2005/12/09 23:48:44
This commit is contained in:
Родитель
9cd026655e
Коммит
d3255db736
|
@ -64,6 +64,7 @@
|
|||
#include "nsUnicharUtils.h"
|
||||
#include "prtime.h"
|
||||
#include "prprf.h"
|
||||
#include "mozStorageHelper.h"
|
||||
|
||||
// emulate string comparison (used for sorting) for PRTime and int
|
||||
inline PRInt32 ComparePRTime(PRTime a, PRTime b)
|
||||
|
@ -177,6 +178,183 @@ NS_IMETHODIMP nsNavHistoryResultNode::GetChild(PRInt32 aIndex,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsINavBookmarkObserver implementation
|
||||
|
||||
/* void onBeginUpdateBatch(); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnBeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onEndUpdateBatch(); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnEndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute boolean wantAllDetails; */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::GetWantAllDetails(PRBool *aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemAdded(in nsIURI bookmark, in PRInt64 folder, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnItemAdded(nsIURI *aBookmark,
|
||||
PRInt64 aFolder,
|
||||
PRInt32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemRemoved(in nsIURI bookmark, in PRInt64 folder, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnItemRemoved(nsIURI *aBookmark,
|
||||
PRInt64 aFolder, PRInt32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemMoved(in nsIURI bookmark, in PRInt64 folder,
|
||||
in PRInt32 oldIndex, in PRInt32 newIndex); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnItemMoved(nsIURI *aBookmark, PRInt64 aFolder,
|
||||
PRInt32 aOldIndex, PRInt32 aNewIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
/* void onItemChanged(in nsIURI bookmark, in ACString property); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnItemChanged(nsIURI *aBookmark,
|
||||
const nsACString &aProperty)
|
||||
{
|
||||
// We let OnPageChanged handle this case
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemReplaced(in PRInt64 folder, in nsIURI item, in nsIURI newItem); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnItemReplaced(PRInt64 aFolder,
|
||||
nsIURI *aItem, nsIURI *aNewItem)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderAdded(in PRInt64 folder, in PRInt64 parent, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnFolderAdded(PRInt64 aFolder,
|
||||
PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderRemoved(in PRInt64 folder, in PRInt64 parent, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnFolderRemoved(PRInt64 aFolder,
|
||||
PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderMoved(in PRInt64 folder,
|
||||
in PRInt64 oldParent, in PRInt32 oldIndex,
|
||||
in PRInt64 newParent, in PRInt32 newIndex); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnFolderMoved(PRInt64 aFolder,
|
||||
PRInt64 aOldParent, PRInt32 aOldIndex,
|
||||
PRInt64 aNewParent, PRInt32 aNewIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderChanged(in PRInt64 folder, in ACString property); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnFolderChanged(PRInt64 aFolder,
|
||||
const nsACString &aProperty)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsINavHistoryObserver implementation
|
||||
|
||||
/* void onAddURI(in nsiURI aURI, in PRTime aTime); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnAddURI(nsIURI *aURI, PRTime aTime)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onDeleteURI(in nsIURI aURI); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnDeleteURI(nsIURI *aURI)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onClearHistory(); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnClearHistory()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onPageChanged(in nsIURI aURI, in PRUint32 aWhat, in AString aValue); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryResultNode::OnPageChanged(nsIURI *aURI,
|
||||
PRUint32 aWhat, const nsAString &aValue)
|
||||
{
|
||||
// We're an item node in a bookmark folder. Check if the given URL
|
||||
// matches ours, and rebuild the row if so.
|
||||
nsCAutoString spec;
|
||||
aURI->GetSpec(spec);
|
||||
if (spec.Equals(mUrl)) {
|
||||
// TODO(bryner): only rebuild if aProperty is being shown
|
||||
Rebuild();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsNavHistoryResult*
|
||||
nsNavHistoryResultNode::GetResult()
|
||||
{
|
||||
nsNavHistoryResultNode *parent, *node = this;
|
||||
while ((parent = node->mParent)) {
|
||||
node = parent;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINavHistoryResult> result = do_QueryInterface(node);
|
||||
NS_ASSERTION(result, "toplevel node must be a result");
|
||||
return NS_STATIC_CAST(nsNavHistoryResult*,
|
||||
NS_STATIC_CAST(nsINavHistoryResult*, result));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistoryResultNode::Rebuild()
|
||||
{
|
||||
if (mID == 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsNavHistory *history = nsNavHistory::GetHistoryService();
|
||||
mozIStorageStatement *statement = history->DBGetURLPageInfo();
|
||||
mozStorageStatementScoper scope(statement);
|
||||
|
||||
nsresult rv = statement->BindInt64Parameter(0, mID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ASSERTION(results, "node must be in history!");
|
||||
|
||||
return history->FillURLResult(statement, this);
|
||||
}
|
||||
|
||||
// nsNavHistoryQueryNode ******************************************************
|
||||
|
||||
nsNavHistoryQueryNode::~nsNavHistoryQueryNode()
|
||||
|
@ -251,8 +429,14 @@ nsNavHistoryQueryNode::GetQueryOptions(nsINavHistoryQueryOptions **aOptions)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistoryQueryNode::BuildChildren()
|
||||
nsNavHistoryQueryNode::BuildChildren(PRBool *aBuilt)
|
||||
{
|
||||
if (mBuiltChildren) {
|
||||
*aBuilt = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aBuilt = PR_TRUE;
|
||||
nsresult rv;
|
||||
if (!mOptions) {
|
||||
rv = ParseQueries();
|
||||
|
@ -272,15 +456,487 @@ nsNavHistoryQueryNode::BuildChildren()
|
|||
mChildren.Clear();
|
||||
NS_ENSURE_TRUE(mChildren.AppendObjects(*(result->GetTopLevel())),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
mBuiltChildren = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistoryQueryNode::UpdateQuery()
|
||||
{
|
||||
mBuiltChildren = PR_FALSE;
|
||||
if (mExpanded) {
|
||||
nsNavHistoryResult *result = GetResult();
|
||||
nsresult rv = result->BuildChildrenFor(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
result->Invalidate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsINavBookmarkObserver implementation
|
||||
|
||||
/* void onBeginUpdateBatch(); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnBeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onEndUpdateBatch(); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnEndUpdateBatch()
|
||||
{
|
||||
// TODO(bryner): Batch updates
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute boolean wantAllDetails; */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::GetWantAllDetails(PRBool *aResult)
|
||||
{
|
||||
*aResult = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistoryQueryNode::CreateNode(nsIURI *aBookmark,
|
||||
nsNavHistoryResultNode **aNode)
|
||||
{
|
||||
nsNavHistory *history = nsNavHistory::GetHistoryService();
|
||||
mozIStorageStatement *statement = history->DBGetURLPageInfoFull();
|
||||
mozStorageStatementScoper scope(statement);
|
||||
|
||||
nsresult rv = BindStatementURI(statement, 0, aBookmark);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(results, "item must be in history!");
|
||||
|
||||
return history->RowToResult(statement, PR_FALSE, aNode);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsNavHistoryQueryNode::HasFilteredChildren() const
|
||||
{
|
||||
if (mQueryCount != 1) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRUint32 itemTypes;
|
||||
mQueries[0]->GetItemTypes(&itemTypes);
|
||||
return itemTypes != (nsINavHistoryQuery::INCLUDE_ITEMS |
|
||||
nsINavHistoryQuery::INCLUDE_QUERIES);
|
||||
}
|
||||
|
||||
/* void onItemAdded(in nsIURI bookmark, in PRInt64 folder, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnItemAdded(nsIURI *aBookmark,
|
||||
PRInt64 aFolder, PRInt32 aIndex)
|
||||
{
|
||||
nsresult rv;
|
||||
if (GetFolderId() == aFolder) {
|
||||
// If we're not expanded, we can just invalidate our child list
|
||||
// and rebuild it the next time we're opened.
|
||||
if (!mExpanded) {
|
||||
mBuiltChildren = PR_FALSE; // causes a rebuild on next open
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're a special query type, just requery.
|
||||
if (HasFilteredChildren()) {
|
||||
rv = UpdateQuery();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
// This node is expanded and is the target of this add, so
|
||||
// create a new result node and insert it.
|
||||
nsRefPtr<nsNavHistoryResultNode> node;
|
||||
rv = CreateNode(aBookmark, getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(mChildren.InsertObjectAt(node, aIndex),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
GetResult()->RowAdded(this, aIndex);
|
||||
}
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnItemAdded(aBookmark, aFolder, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemRemoved(in nsIURI bookmark, in PRInt64 folder, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnItemRemoved(nsIURI *aBookmark,
|
||||
PRInt64 aFolder, PRInt32 aIndex)
|
||||
{
|
||||
if (GetFolderId() == aFolder) {
|
||||
// If we're not expanded, we can just invalidate our child list
|
||||
// and rebuild it the next time we're opened.
|
||||
if (!mExpanded) {
|
||||
mBuiltChildren = PR_FALSE; // causes a rebuild on next open
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're a special query type, just requery.
|
||||
if (HasFilteredChildren()) {
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
// Remove the ResultNode for the URI
|
||||
PRInt32 index = mChildren[aIndex]->VisibleIndex();
|
||||
mChildren.RemoveObjectAt(aIndex);
|
||||
GetResult()->RowRemoved(index);
|
||||
}
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
nsresult rv = mChildren[i]->OnItemRemoved(aBookmark, aFolder, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemMoved(in nsIURI bookmark, in PRInt64 folder,
|
||||
in PRInt32 oldIndex, in PRInt32 newIndex); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnItemMoved(nsIURI *aBookmark, PRInt64 aFolder,
|
||||
PRInt32 aOldIndex, PRInt32 aNewIndex)
|
||||
{
|
||||
if (GetFolderId() == aFolder) {
|
||||
// If we're not expanded, we can just invalidate our child list
|
||||
// and rebuild it the next time we're opened.
|
||||
if (!mExpanded) {
|
||||
mBuiltChildren = PR_FALSE; // causes a rebuild on next open
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're a special query type, just requery.
|
||||
if (HasFilteredChildren()) {
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
nsRefPtr<nsNavHistoryResultNode> node = mChildren[aOldIndex];
|
||||
PRInt32 delta = (aNewIndex > aOldIndex) ? 1 : -1;
|
||||
for (PRInt32 i = aOldIndex; i != aNewIndex; i += delta) {
|
||||
mChildren.ReplaceObjectAt(mChildren[i + delta], i);
|
||||
}
|
||||
mChildren.ReplaceObjectAt(node, aNewIndex);
|
||||
// TODO(bryner): we should only invalidate the affected rows
|
||||
GetResult()->Invalidate();
|
||||
}
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
nsresult rv = mChildren[i]->OnItemMoved(aBookmark, aFolder,
|
||||
aOldIndex, aNewIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemChanged(in nsIURI bookmark, in ACString property); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnItemChanged(nsIURI *aBookmark,
|
||||
const nsACString &aProperty)
|
||||
{
|
||||
// We let OnPageChanged handle this case.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onItemReplaced(in PRInt64 folder, in nsIURI item, in nsIURI newItem); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnItemReplaced(PRInt64 aFolder,
|
||||
nsIURI *aItem, nsIURI *aNewItem)
|
||||
{
|
||||
nsresult rv;
|
||||
if (GetFolderId() == aFolder) {
|
||||
// If we're not expanded, we can just invalidate our child list
|
||||
// and rebuild it the next time we're opened.
|
||||
if (!mExpanded) {
|
||||
mBuiltChildren = PR_FALSE; // causes a rebuild on next open
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're a special query type, just requery.
|
||||
if (HasFilteredChildren()) {
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
// Replace the old node (aItem) with a new node for aNewItem.
|
||||
// We copy the indices from aItem since it is at the same location.
|
||||
nsRefPtr<nsNavHistoryResultNode> node;
|
||||
rv = CreateNode(aNewItem, getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
PRInt32 index;
|
||||
bookmarks->IndexOfItem(aFolder, aNewItem, &index);
|
||||
|
||||
PRInt32 visibleIndex = mChildren[index]->VisibleIndex();
|
||||
node->SetParent(this);
|
||||
node->SetVisibleIndex(visibleIndex);
|
||||
node->SetIndentLevel(mChildren[index]->IndentLevel());
|
||||
mChildren.ReplaceObjectAt(node, index);
|
||||
GetResult()->RowChanged(node->VisibleIndex());
|
||||
}
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnItemReplaced(aFolder, aItem, aNewItem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderAdded(in PRInt64 folder, in PRInt64 parent, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnFolderAdded(PRInt64 aFolder,
|
||||
PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
nsresult rv;
|
||||
if (GetFolderId() == aParent) {
|
||||
// If we're not expanded, we can just invalidate our child list
|
||||
// and rebuild it the next time we're opened.
|
||||
if (!mExpanded) {
|
||||
mBuiltChildren = PR_FALSE; // causes a rebuild on next open
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're a special query type, just requery.
|
||||
if (HasFilteredChildren()) {
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
// This node is expanded and is the target of this add, so
|
||||
// create a new result node and insert it.
|
||||
nsRefPtr<nsNavHistoryResultNode> node;
|
||||
rv = nsNavBookmarks::GetBookmarksService()->
|
||||
ResultNodeForFolder(aFolder, mQueries[0], mOptions,
|
||||
getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(mChildren.InsertObjectAt(node, aIndex),
|
||||
NS_ERROR_OUT_OF_MEMORY);
|
||||
GetResult()->RowAdded(this, aIndex);
|
||||
}
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnFolderAdded(aFolder, aParent, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderRemoved(in PRInt64 folder, in PRInt64 parent, in PRInt32 index); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnFolderRemoved(PRInt64 aFolder,
|
||||
PRInt64 aParent, PRInt32 aIndex)
|
||||
{
|
||||
if (GetFolderId() == aParent) {
|
||||
// If we're not expanded, we can just invalidate our child list
|
||||
// and rebuild it the next time we're opened.
|
||||
if (!mExpanded) {
|
||||
mBuiltChildren = PR_FALSE; // causes a rebuild on next open
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're a special query type, just requery.
|
||||
if (HasFilteredChildren()) {
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
// Remove the folder node from our child list.
|
||||
PRInt32 index = mChildren[aIndex]->VisibleIndex();
|
||||
mChildren.RemoveObjectAt(aIndex);
|
||||
GetResult()->RowRemoved(index);
|
||||
}
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
nsresult rv = mChildren[i]->OnFolderRemoved(aFolder, aParent, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderMoved(in PRInt64 folder,
|
||||
in PRInt64 oldParent, in PRInt32 oldIndex,
|
||||
in PRInt64 newParent, in PRInt32 newIndex); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnFolderMoved(PRInt64 aFolder,
|
||||
PRInt64 aOldParent, PRInt32 aOldIndex,
|
||||
PRInt64 aNewParent, PRInt32 aNewIndex)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt64 nodeFolder = GetFolderId();
|
||||
|
||||
if (aOldParent == aNewParent && aOldParent == nodeFolder) {
|
||||
// If we're not expanded, we can just invalidate our child list
|
||||
// and rebuild it the next time we're opened.
|
||||
if (!mExpanded) {
|
||||
mBuiltChildren = PR_FALSE; // causes a rebuild on next open
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we're a special query type, just requery.
|
||||
if (HasFilteredChildren()) {
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
nsRefPtr<nsNavHistoryResultNode> node = mChildren[aOldIndex];
|
||||
PRInt32 delta = (aNewIndex > aOldIndex) ? 1 : -1;
|
||||
for (PRInt32 i = aOldIndex; i != aNewIndex; i += delta) {
|
||||
mChildren.ReplaceObjectAt(mChildren[i + delta], i);
|
||||
}
|
||||
mChildren.ReplaceObjectAt(node, aNewIndex);
|
||||
// TODO(bryner): we should only invalidate the affected rows
|
||||
GetResult()->Invalidate();
|
||||
}
|
||||
} else if (aOldParent == nodeFolder) {
|
||||
OnFolderRemoved(aFolder, aOldParent, aOldIndex);
|
||||
} else if (aNewParent == nodeFolder) {
|
||||
OnFolderAdded(aFolder, aNewParent, aNewIndex);
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnFolderMoved(aFolder,
|
||||
aOldParent, aOldIndex,
|
||||
aNewParent, aNewIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onFolderChanged(in PRInt64 folder, in ACString property); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnFolderChanged(PRInt64 aFolder,
|
||||
const nsACString &aProperty)
|
||||
{
|
||||
if (GetFolderId() == aFolder) {
|
||||
// TODO(bryner): only rebuild if aProperty is being shown
|
||||
Rebuild();
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
nsresult rv = mChildren[i]->OnFolderChanged(aFolder, aProperty);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsINavHistoryObserver implementation
|
||||
|
||||
/* void onAddURI(in nsiURI aURI, in PRTime aTime); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnAddURI(nsIURI *aURI, PRTime aTime)
|
||||
{
|
||||
nsresult rv;
|
||||
if (GetFolderId() == 0) {
|
||||
// We're a non-folder query, so we need to requery.
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnAddURI(aURI, aTime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onDeleteURI(in nsIURI aURI); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnDeleteURI(nsIURI *aURI)
|
||||
{
|
||||
nsresult rv;
|
||||
if (GetFolderId() == 0) {
|
||||
// We're a non-folder query, so we need to requery.
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnDeleteURI(aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onClearHistory(); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnClearHistory()
|
||||
{
|
||||
nsresult rv;
|
||||
if (GetFolderId() == 0) {
|
||||
// We're a non-folder query, so we need to requery.
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnClearHistory();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onPageChanged(in nsIURI aURI, in PRUint32 aWhat, in AString aValue); */
|
||||
NS_IMETHODIMP
|
||||
nsNavHistoryQueryNode::OnPageChanged(nsIURI *aURI,
|
||||
PRUint32 aWhat, const nsAString &aValue)
|
||||
{
|
||||
nsresult rv;
|
||||
PRInt64 folder = nsNavHistoryQueryNode::GetFolderId();
|
||||
if (folder == 0) {
|
||||
// If we're a query node (other than a folder), we need to re-execute
|
||||
// our queries in case aBookmark should be added/removed from the
|
||||
// results.
|
||||
return UpdateQuery();
|
||||
} else {
|
||||
// We're a bookmark folder. Run through our children and notify them.
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
rv = mChildren[i]->OnPageChanged(aURI, aWhat, aValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistoryQueryNode::Rebuild()
|
||||
{
|
||||
PRInt64 folderId = GetFolderId();
|
||||
if (folderId != 0) {
|
||||
nsNavBookmarks *bookmarks = nsNavBookmarks::GetBookmarksService();
|
||||
mozIStorageStatement *statement = bookmarks->DBGetFolderInfo();
|
||||
mozStorageStatementScoper scope(statement);
|
||||
|
||||
nsresult rv = statement->BindInt64Parameter(0, folderId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRBool results;
|
||||
rv = statement->ExecuteStep(&results);
|
||||
NS_ASSERTION(results, "folder must be in db");
|
||||
|
||||
return bookmarks->FillFolderNode(statement, this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsNavHistoryResult **********************************************************
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsNavHistoryResult, nsNavHistoryResultNode,
|
||||
NS_IMPL_ISUPPORTS_INHERITED5(nsNavHistoryResult, nsNavHistoryQueryNode,
|
||||
nsINavHistoryResult,
|
||||
nsITreeView)
|
||||
nsITreeView,
|
||||
nsINavBookmarkObserver,
|
||||
nsINavHistoryObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
|
||||
// nsNavHistoryResult::nsNavHistoryResult
|
||||
|
@ -317,14 +973,16 @@ nsNavHistoryResult::nsNavHistoryResult(nsNavHistory* aHistoryService,
|
|||
aOptions->Clone(getter_AddRefs(mOptions));
|
||||
|
||||
mType = nsINavHistoryResult::RESULT_TYPE_QUERY;
|
||||
mFlatIndex = -1;
|
||||
mVisibleIndex = -1;
|
||||
mExpanded = PR_TRUE; // the result itself can never be "collapsed"
|
||||
}
|
||||
|
||||
// nsNavHistoryResult::~nsNavHistoryResult
|
||||
|
||||
nsNavHistoryResult::~nsNavHistoryResult()
|
||||
{
|
||||
nsNavBookmarks::GetBookmarksService()->RemoveObserver(this);
|
||||
nsNavHistory::GetHistoryService()->RemoveObserver(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -352,6 +1010,10 @@ nsNavHistoryResult::Init()
|
|||
mDateFormatter = do_CreateInstance(kDateTimeFormatCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Hook up as an observer
|
||||
nsNavBookmarks::GetBookmarksService()->AddObserver(this, PR_TRUE);
|
||||
nsNavHistory::GetHistoryService()->AddObserver(this, PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -375,10 +1037,15 @@ nsNavHistoryResult::FilledAllResults()
|
|||
nsresult
|
||||
nsNavHistoryResult::BuildChildrenFor(nsNavHistoryResultNode *aNode)
|
||||
{
|
||||
nsresult rv = aNode->BuildChildren();
|
||||
PRBool built;
|
||||
nsresult rv = aNode->BuildChildren(&built);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!built) {
|
||||
// No children needed to be built.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32 flatIndex = aNode->mFlatIndex + 1;
|
||||
PRInt32 flatIndex = mAllElements.IndexOf(aNode) + 1;
|
||||
for (PRInt32 i = 0; i < aNode->mChildren.Count(); ++i) {
|
||||
nsNavHistoryResultNode *child = aNode->mChildren[i];
|
||||
|
||||
|
@ -629,11 +1296,13 @@ nsNavHistoryResult::RemoveObserver(nsINavHistoryResultViewObserver* aObserver)
|
|||
//
|
||||
// This is called to assign the correct arrow to the column header. It is
|
||||
// called both when you resort, and when a tree is first attached (to
|
||||
// initialize it's headers).
|
||||
// initialize its headers).
|
||||
|
||||
void
|
||||
nsNavHistoryResult::SetTreeSortingIndicator()
|
||||
{
|
||||
NS_ASSERTION(mTree, "should only be called if we have a tree");
|
||||
|
||||
nsCOMPtr<nsITreeColumns> columns;
|
||||
nsresult rv = mTree->GetColumns(getter_AddRefs(columns));
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
@ -881,9 +1550,7 @@ nsNavHistoryResult::RebuildAllListRecurse(
|
|||
AllElementAt(allCount - 1)->mID == aSource[i]->mID) {
|
||||
// ignore duplicate, that elements' flat index is the index of its dup
|
||||
// note, we don't collapse ID=0 elements since that is all parent nodes
|
||||
aSource[i]->mFlatIndex = allCount - 1;
|
||||
} else {
|
||||
aSource[i]->mFlatIndex = mAllElements.Count();
|
||||
mAllElements.AppendElement(aSource[i]);
|
||||
if (aSource[i]->mChildren.Count() > 0)
|
||||
RebuildAllListRecurse(aSource[i]->mChildren);
|
||||
|
@ -1496,3 +2163,40 @@ nsNavHistoryResult::SortTypeToColumnType(PRUint32 aSortType,
|
|||
return Column_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsNavHistoryResult::RowAdded(nsNavHistoryResultNode *aParent, PRInt32 aIndex)
|
||||
{
|
||||
mAllElements.Clear();
|
||||
mVisibleElements.Clear();
|
||||
FilledAllResults();
|
||||
if (mTree) {
|
||||
mTree->RowCountChanged(aParent->ChildAt(aIndex)->mVisibleIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsNavHistoryResult::RowRemoved(PRInt32 aVisibleIndex)
|
||||
{
|
||||
mAllElements.Clear();
|
||||
mVisibleElements.Clear();
|
||||
FilledAllResults();
|
||||
if (mTree) {
|
||||
mTree->RowCountChanged(aVisibleIndex, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsNavHistoryResult::RowChanged(PRInt32 aVisibleIndex)
|
||||
{
|
||||
if (mTree) {
|
||||
mTree->InvalidateRow(aVisibleIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsNavHistoryResult::Invalidate()
|
||||
{
|
||||
FillTreeStats(this, -1);
|
||||
RebuildList();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче