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:
benjamin%smedbergs.us 2006-07-18 18:13:23 +00:00
Родитель 9cd026655e
Коммит d3255db736
1 изменённых файлов: 713 добавлений и 9 удалений

Просмотреть файл

@ -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();
}