зеркало из https://github.com/mozilla/pjs.git
Landing bookmarks changes.
Bug 205378 - Meta bug for changes in bookmarks sorting code r=jag, sr=sspitzer, a=sspitzer,asa The CloneResource() has been back ported from Firebird, originally implemented by Pierre Chanial.
This commit is contained in:
Родитель
beaec6185a
Коммит
1734eec58f
|
@ -853,8 +853,8 @@ var BookmarksToolbarRDFObserver =
|
|||
},
|
||||
onChange: function (aDataSource, aSource, aProperty, aOldTarget, aNewTarget) {},
|
||||
onMove: function (aDataSource, aOldSource, aNewSource, aProperty, aTarget) {},
|
||||
beginUpdateBatch: function (aDataSource) {},
|
||||
endUpdateBatch: function (aDataSource) {},
|
||||
onBeginUpdateBatch: function (aDataSource) {},
|
||||
onEndUpdateBatch: function (aDataSource) {},
|
||||
|
||||
_overflowTimerInEffect: false,
|
||||
setOverflowTimeout: function (aSource, aProperty)
|
||||
|
|
|
@ -609,13 +609,11 @@
|
|||
default:
|
||||
this.mOuter.saveSelection();
|
||||
// Notify the datasource that we're about to begin a batch operation
|
||||
//var observer = this.mOuter.tree.builder.QueryInterface(Components.interfaces.nsIRDFObserver);
|
||||
//observer.beginUpdateBatch(this.db);
|
||||
//BMDS.beginUpdateBatch();
|
||||
BookmarksController.doCommand(aCommand, selection, target);
|
||||
//observer.endUpdateBatch(this.db);
|
||||
//BMDS.endUpdateBatch();
|
||||
//var firstVisibleRow = this.mOuter.treeBoxObject.getFirstVisibleRow()
|
||||
//this.mOuter.treeBoxObject.selection.currentIndex=-1;
|
||||
//this.mOuter.tree.builder.rebuild();
|
||||
// temporary hack: for an unknown reason, rebuilding cause a scroll to the bottom
|
||||
// if the first visible row is not 0
|
||||
//this.mOuter.treeBoxObject.scrollToRow(firstVisibleRow);
|
||||
|
@ -678,8 +676,7 @@
|
|||
//var firstVisibleRow = this.mOuter.treeBoxObject.getFirstVisibleRow()
|
||||
this.mOuter.treeBoxObject.selection.selectEventsSuppressed = true;
|
||||
// Notify the datasource that we're about to begin a batch operation
|
||||
//var observer = this.mOuter.tree.builder.QueryInterface(Components.interfaces.nsIRDFObserver);
|
||||
//observer.beginUpdateBatch(this.db);
|
||||
//BMDS.beginUpdateBatch();
|
||||
const kDSIID = Components.interfaces.nsIDragService;
|
||||
const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
|
||||
|
||||
|
@ -687,9 +684,8 @@
|
|||
BookmarksUtils.insertSelection("drag", selection, target);
|
||||
else
|
||||
BookmarksUtils.moveSelection ("drag", selection, target);
|
||||
//observer.endUpdateBatch(this.db);
|
||||
//BMDS.endUpdateBatch();
|
||||
//this.mOuter.treeBoxObject.selection.currentIndex=-1;
|
||||
//this.mOuter.treeBuilder.rebuild();
|
||||
// temporary hack: for an unknown reason, rebuilding cause a scroll to the bottom
|
||||
// if the first visible row is not 0
|
||||
//this.mOuter.treeBoxObject.scrollToRow(firstVisibleRow);
|
||||
|
|
|
@ -3395,9 +3395,9 @@ nsBookmarksService::ImportSystemBookmarks(nsIRDFResource* aParentFolder)
|
|||
|
||||
BookmarkParser parser;
|
||||
parser.Init(ieFavoritesFile, mInner);
|
||||
BeginUpdateBatch(this);
|
||||
BeginUpdateBatch();
|
||||
parser.Parse(aParentFolder, kNC_Bookmark);
|
||||
EndUpdateBatch(this);
|
||||
EndUpdateBatch();
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
|
@ -4526,9 +4526,9 @@ nsBookmarksService::ReadFavorites()
|
|||
{
|
||||
BookmarkParser parser;
|
||||
parser.Init(ieFavoritesFile, mInner);
|
||||
BeginUpdateBatch(this);
|
||||
BeginUpdateBatch();
|
||||
parser.Parse(kNC_IEFavoritesRoot, kNC_IEFavorite);
|
||||
EndUpdateBatch(this);
|
||||
EndUpdateBatch();
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> ieTitleLiteral;
|
||||
rv = gRDF->GetLiteral(ieTitle.get(), getter_AddRefs(ieTitleLiteral));
|
||||
|
@ -4703,9 +4703,9 @@ nsBookmarksService::LoadBookmarks()
|
|||
parser.ParserFoundIEFavoritesRoot(&foundIERoot);
|
||||
}
|
||||
|
||||
BeginUpdateBatch(this);
|
||||
BeginUpdateBatch();
|
||||
parser.Parse(kNC_BookmarksRoot, kNC_Bookmark);
|
||||
EndUpdateBatch(this);
|
||||
EndUpdateBatch();
|
||||
mBookmarksAvailable = PR_TRUE;
|
||||
|
||||
PRBool foundPTFolder = PR_FALSE;
|
||||
|
@ -5536,13 +5536,13 @@ nsBookmarksService::OnMove(nsIRDFDataSource* aDataSource,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsBookmarksService::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
if (mUpdateBatchNest++ == 0)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
(void) mObservers[i]->BeginUpdateBatch(aDataSource);
|
||||
(void) mObservers[i]->OnBeginUpdateBatch(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5550,7 +5550,7 @@ nsBookmarksService::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsBookmarksService::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
if (mUpdateBatchNest > 0)
|
||||
{
|
||||
|
@ -5561,7 +5561,7 @@ nsBookmarksService::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
|||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
(void) mObservers[i]->EndUpdateBatch(aDataSource);
|
||||
(void) mObservers[i]->OnEndUpdateBatch(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -286,6 +286,14 @@ public:
|
|||
nsIRDFResource* aCommand,
|
||||
nsISupportsArray/*<nsIRDFResource>*/* aArguments);
|
||||
|
||||
NS_IMETHOD BeginUpdateBatch() {
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHOD EndUpdateBatch() {
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
||||
// nsIRDFRemoteDataSource
|
||||
NS_DECL_NSIRDFREMOTEDATASOURCE
|
||||
|
||||
|
|
|
@ -166,19 +166,13 @@ var downloadViewController = {
|
|||
gDownloadManager.startBatchUpdate();
|
||||
|
||||
// Notify the datasource that we're about to begin a batch operation
|
||||
var observer = gDownloadHistoryView.builder.QueryInterface(Components.interfaces.nsIRDFObserver);
|
||||
var ds = gDownloadHistoryView.database;
|
||||
observer.beginUpdateBatch(ds);
|
||||
|
||||
gDownloadManager.datasource.beginUpdateBatch();
|
||||
for (i = 0; i <= selectedItems.length - 1; ++i) {
|
||||
gDownloadManager.removeDownload(selectedItems[i].id);
|
||||
}
|
||||
gDownloadManager.datasource.endUpdateBatch();
|
||||
|
||||
gDownloadManager.endBatchUpdate();
|
||||
observer.endUpdateBatch(ds);
|
||||
var remote = gDownloadManager.datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
|
||||
remote.Flush();
|
||||
gDownloadHistoryView.builder.rebuild();
|
||||
var rowCount = gDownloadHistoryView.getRowCount();
|
||||
if (selectedIndex > ( rowCount- 1))
|
||||
selectedIndex = rowCount - 1;
|
||||
|
|
|
@ -679,8 +679,12 @@ nsDownloadManager::StartBatchUpdate()
|
|||
NS_IMETHODIMP
|
||||
nsDownloadManager::EndBatchUpdate()
|
||||
{
|
||||
--mBatches;
|
||||
return NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
if (--mBatches == 0) {
|
||||
nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mDataSource);
|
||||
rv = remote->Flush();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -216,10 +216,6 @@ var PrivacyPanel = {
|
|||
}
|
||||
dlMgr.endBatchUpdate();
|
||||
|
||||
var rds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
|
||||
if (rds)
|
||||
rds.Flush();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -287,6 +287,16 @@ nsChromeUIDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|||
return mComposite->DoCommand(aSources, aCommand, aArguments);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::BeginUpdateBatch() {
|
||||
return mComposite->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::EndUpdateBatch() {
|
||||
return mComposite->EndUpdateBatch();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -299,7 +309,6 @@ nsChromeUIDataSource::OnAssert(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnAssert(this, aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -313,7 +322,6 @@ nsChromeUIDataSource::OnUnassert(nsIRDFDataSource* aDataSource,
|
|||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnUnassert(aDataSource, aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -330,7 +338,6 @@ nsChromeUIDataSource::OnChange(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnChange(aDataSource, aSource, aProperty, aOldTarget, aNewTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -347,20 +354,29 @@ nsChromeUIDataSource::OnMove(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnMove(aDataSource, aOldSource, aNewSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsChromeUIDataSource::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnBeginUpdateBatch(aDataSource);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsChromeUIDataSource::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnEndUpdateBatch(aDataSource);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -290,6 +290,7 @@ XUL_ATOM(dir, "dir")
|
|||
XUL_ATOM(properties, "properties")
|
||||
XUL_ATOM(resource, "resource")
|
||||
XUL_ATOM(sort, "sort")
|
||||
XUL_ATOM(sortLocked, "sortLocked")
|
||||
XUL_ATOM(sortDirection, "sortDirection")
|
||||
XUL_ATOM(sortActive, "sortActive")
|
||||
XUL_ATOM(sortResource, "sortResource")
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
nsIXULSortService.idl
|
||||
nsIXULTemplateBuilder.idl
|
|
@ -31,6 +31,7 @@ MODULE = xultmpl
|
|||
XPIDLSRCS = \
|
||||
nsIXULSortService.idl \
|
||||
nsIXULTemplateBuilder.idl \
|
||||
nsIXULBuilderListener.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jan Varga <varga@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIXULTemplateBuilder;
|
||||
|
||||
// An nsIXULBuilderListener object is a listener that will be notified
|
||||
// when a template builder rebuilds its content.
|
||||
[scriptable, uuid(ac46be8f-c863-4c23-84a2-d0fcc8dfa9f4)]
|
||||
interface nsIXULBuilderListener: nsISupports {
|
||||
|
||||
/**
|
||||
* Called before a template builder rebuilds its content.
|
||||
* @param aBuilder the template builder that rebuilds the content.
|
||||
*/
|
||||
void willRebuild(in nsIXULTemplateBuilder aBuilder);
|
||||
|
||||
/**
|
||||
* Called after a template builder has rebuilt its content.
|
||||
* @param aBuilder the template builder that has rebuilt the content.
|
||||
*/
|
||||
void didRebuild(in nsIXULTemplateBuilder aBuilder);
|
||||
|
||||
};
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Chris Waterson <waterson@netscape.com>
|
||||
* Ben Goodger <ben@netscape.com>
|
||||
* Jan Varga <varga@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -43,6 +44,8 @@
|
|||
#include "nsIRDFCompositeDataSource.idl"
|
||||
#include "nsIRDFResource.idl"
|
||||
|
||||
interface nsIXULBuilderListener;
|
||||
|
||||
[ptr] native nsIContent_ptr(nsIContent);
|
||||
|
||||
[scriptable, uuid(fb744f8e-1dd1-11b2-a5d7-935c9ab60602)]
|
||||
|
@ -77,6 +80,17 @@ interface nsIXULTemplateBuilder : nsISupports
|
|||
* built.
|
||||
*/
|
||||
[noscript] void createContents(in nsIContent_ptr aElement);
|
||||
|
||||
/**
|
||||
* Add a listener to this template builder. The template builder
|
||||
* holds a strong reference to the listener.
|
||||
*/
|
||||
void addListener(in nsIXULBuilderListener aListener);
|
||||
|
||||
/**
|
||||
* Remove a listener from this template builder.
|
||||
*/
|
||||
void removeListener(in nsIXULBuilderListener aListener);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -130,7 +130,6 @@ class nsXULContentBuilder : public nsXULTemplateBuilder
|
|||
{
|
||||
public:
|
||||
// nsIXULTemplateBuilder interface
|
||||
NS_IMETHOD Rebuild();
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement);
|
||||
|
||||
// nsIDocumentObserver interface
|
||||
|
@ -243,6 +242,9 @@ protected:
|
|||
virtual nsresult
|
||||
InitializeRuleNetworkForSimpleRules(InnerNode** aChildNode);
|
||||
|
||||
virtual nsresult
|
||||
RebuildAll();
|
||||
|
||||
virtual nsresult
|
||||
CompileCondition(nsIAtom* aTag,
|
||||
nsTemplateRule* aRule,
|
||||
|
@ -288,9 +290,6 @@ protected:
|
|||
*/
|
||||
nsRDFSortState sortState;
|
||||
|
||||
nsresult
|
||||
Rebuild(nsIContent* aElement);
|
||||
|
||||
virtual nsresult
|
||||
ReplaceMatch(nsIRDFResource* aMember, const nsTemplateMatch* aOldMatch, nsTemplateMatch* aNewMatch);
|
||||
|
||||
|
@ -1671,77 +1670,6 @@ nsXULContentBuilder::GetElementFactory(PRInt32 aNameSpaceID, nsIElementFactory**
|
|||
// nsIXULTemplateBuilder methods
|
||||
//
|
||||
|
||||
nsresult
|
||||
nsXULContentBuilder::Rebuild(nsIContent* aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Next, see if it's a XUL element whose contents have never even
|
||||
// been generated. If so, short-circuit and bail; there's nothing
|
||||
// for us to "rebuild" yet. They'll get built correctly the next
|
||||
// time somebody asks for them.
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(aElement);
|
||||
|
||||
if (xulcontent) {
|
||||
PRBool containerContentsBuilt = PR_FALSE;
|
||||
xulcontent->GetLazyState(nsIXULContent::eContainerContentsBuilt, containerContentsBuilt);
|
||||
|
||||
if (! containerContentsBuilt)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we get here, then we've tried to generate content for this
|
||||
// element. Remove it.
|
||||
rv = RemoveGeneratedContent(aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aElement == mRoot) {
|
||||
// Nuke the content support map and conflict set completely.
|
||||
mContentSupportMap.Clear();
|
||||
mTemplateMap.Clear();
|
||||
mConflictSet.Clear();
|
||||
|
||||
rv = CompileRules();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// Forces the XUL element to remember that it needs to
|
||||
// re-generate its children next time around.
|
||||
if (xulcontent) {
|
||||
xulcontent->SetLazyState(nsIXULContent::eChildrenMustBeRebuilt);
|
||||
xulcontent->ClearLazyState(nsIXULContent::eTemplateContentsBuilt);
|
||||
xulcontent->ClearLazyState(nsIXULContent::eContainerContentsBuilt);
|
||||
}
|
||||
|
||||
// Now, regenerate both the template- and container-generated
|
||||
// contents for the current element...
|
||||
nsCOMPtr<nsIContent> container;
|
||||
PRInt32 newIndex;
|
||||
CreateTemplateAndContainerContents(aElement, getter_AddRefs(container), &newIndex);
|
||||
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mRoot->GetDocument(*getter_AddRefs(doc));
|
||||
NS_ASSERTION(doc != nsnull, "root element has no document");
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
doc->ContentAppended(container, newIndex);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULContentBuilder::Rebuild()
|
||||
{
|
||||
return Rebuild(mRoot);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULContentBuilder::CreateContents(nsIContent* aElement)
|
||||
{
|
||||
|
@ -2078,6 +2006,75 @@ nsXULContentBuilder::InitializeRuleNetworkForSimpleRules(InnerNode** aChildNode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULContentBuilder::RebuildAll()
|
||||
{
|
||||
NS_PRECONDITION(mRoot != nsnull, "not initialized");
|
||||
if (! mRoot)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsresult rv = mRoot->GetDocument(*getter_AddRefs(doc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Bail out early if we are being torn down.
|
||||
if (!doc)
|
||||
return NS_OK;
|
||||
|
||||
// See if it's a XUL element whose contents have never even
|
||||
// been generated. If so, short-circuit and bail; there's nothing
|
||||
// for us to "rebuild" yet. They'll get built correctly the next
|
||||
// time somebody asks for them.
|
||||
nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(mRoot);
|
||||
|
||||
if (xulcontent) {
|
||||
PRBool containerContentsBuilt = PR_FALSE;
|
||||
xulcontent->GetLazyState(nsIXULContent::eContainerContentsBuilt, containerContentsBuilt);
|
||||
|
||||
if (! containerContentsBuilt)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we get here, then we've tried to generate content for this
|
||||
// element. Remove it.
|
||||
rv = RemoveGeneratedContent(mRoot);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Nuke the content support map and conflict set completely.
|
||||
mContentSupportMap.Clear();
|
||||
mTemplateMap.Clear();
|
||||
mConflictSet.Clear();
|
||||
|
||||
rv = CompileRules();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Forces the XUL element to remember that it needs to
|
||||
// re-generate its children next time around.
|
||||
if (xulcontent) {
|
||||
xulcontent->SetLazyState(nsIXULContent::eChildrenMustBeRebuilt);
|
||||
xulcontent->ClearLazyState(nsIXULContent::eTemplateContentsBuilt);
|
||||
xulcontent->ClearLazyState(nsIXULContent::eContainerContentsBuilt);
|
||||
}
|
||||
|
||||
// Now, regenerate both the template- and container-generated
|
||||
// contents for the current element...
|
||||
nsCOMPtr<nsIContent> container;
|
||||
PRInt32 newIndex;
|
||||
CreateTemplateAndContainerContents(mRoot, getter_AddRefs(container), &newIndex);
|
||||
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mRoot->GetDocument(*getter_AddRefs(doc));
|
||||
NS_ASSERTION(doc != nsnull, "root element has no document");
|
||||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
doc->ContentAppended(container, newIndex);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULContentBuilder::CompileCondition(nsIAtom* aTag,
|
||||
nsTemplateRule* aRule,
|
||||
|
|
|
@ -226,6 +226,7 @@ nsXULContentUtils::GetElementResource(nsIContent* aElement, nsIRDFResource** aRe
|
|||
nsresult
|
||||
nsXULContentUtils::GetElementRefResource(nsIContent* aElement, nsIRDFResource** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
// Perform a reverse mapping from an element in the content model
|
||||
// to an RDF resource. Check for a "ref" attribute first, then
|
||||
// fallback on an "id" attribute.
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIXULDocument.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsIXULBuilderListener.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
|
@ -151,7 +152,6 @@ PRLogModuleInfo* gXULTemplateLog;
|
|||
nsXULTemplateBuilder::nsXULTemplateBuilder(void)
|
||||
: mDB(nsnull),
|
||||
mRoot(nsnull),
|
||||
mTimer(nsnull),
|
||||
mUpdateBatchNest(0),
|
||||
mRulesCompiled(PR_FALSE),
|
||||
mFlags(0),
|
||||
|
@ -227,6 +227,22 @@ nsXULTemplateBuilder::GetDatabase(nsIRDFCompositeDataSource** aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::Rebuild()
|
||||
{
|
||||
for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i) {
|
||||
mListeners[i]->WillRebuild(this);
|
||||
}
|
||||
|
||||
nsresult rv = RebuildAll();
|
||||
|
||||
for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i) {
|
||||
mListeners[i]->DidRebuild(this);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::Init(nsIContent* aElement)
|
||||
{
|
||||
|
@ -241,6 +257,26 @@ nsXULTemplateBuilder::CreateContents(nsIContent* aElement)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::AddListener(nsIXULBuilderListener* aListener)
|
||||
{
|
||||
NS_ENSURE_ARG(aListener);
|
||||
|
||||
mListeners.AppendObject(aListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::RemoveListener(nsIXULBuilderListener* aListener)
|
||||
{
|
||||
NS_ENSURE_ARG(aListener);
|
||||
|
||||
mListeners.RemoveObject(aListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIDocumentOberver interface
|
||||
|
@ -613,7 +649,7 @@ nsXULTemplateBuilder::OnMove(nsIRDFDataSource* aDataSource,
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsXULTemplateBuilder::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
mUpdateBatchNest++;
|
||||
return NS_OK;
|
||||
|
@ -621,10 +657,12 @@ nsXULTemplateBuilder::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsXULTemplateBuilder::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
if (mUpdateBatchNest > 0)
|
||||
--mUpdateBatchNest;
|
||||
NS_ASSERTION(mUpdateBatchNest > 0, "badly nested update batch");
|
||||
if (--mUpdateBatchNest == 0) {
|
||||
Rebuild();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
|
||||
#include "nsConflictSet.h"
|
||||
|
@ -60,6 +59,7 @@
|
|||
#include "nsResourceSet.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
#include "prlog.h"
|
||||
#ifdef PR_LOGGING
|
||||
|
@ -91,12 +91,8 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIXULTemplateBuilder interface
|
||||
NS_IMETHOD GetRoot(nsIDOMElement** aResult);
|
||||
NS_IMETHOD GetDatabase(nsIRDFCompositeDataSource** aResult);
|
||||
NS_IMETHOD Rebuild() = 0; // must be implemented by subclasses
|
||||
NS_IMETHOD Init(nsIContent* aElement);
|
||||
NS_IMETHOD CreateContents(nsIContent* aElement);
|
||||
|
||||
NS_DECL_NSIXULTEMPLATEBUILDER
|
||||
|
||||
// nsISecurityCheckedComponent
|
||||
NS_DECL_NSISECURITYCHECKEDCOMPONENT
|
||||
|
||||
|
@ -125,6 +121,9 @@ public:
|
|||
virtual nsresult
|
||||
InitializeRuleNetworkForSimpleRules(InnerNode** aChildNode) = 0;
|
||||
|
||||
virtual nsresult
|
||||
RebuildAll() = 0; // must be implemented by subclasses
|
||||
|
||||
/**
|
||||
* Find the <template> tag that applies for this builder
|
||||
*/
|
||||
|
@ -311,7 +310,8 @@ protected:
|
|||
nsCOMPtr<nsIContent> mRoot;
|
||||
|
||||
nsCOMPtr<nsIRDFDataSource> mCache;
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
nsCOMArray<nsIXULBuilderListener> mListeners;
|
||||
|
||||
PRInt32 mUpdateBatchNest;
|
||||
|
||||
|
|
|
@ -92,9 +92,6 @@ public:
|
|||
// nsITreeView
|
||||
NS_DECL_NSITREEVIEW
|
||||
|
||||
// nsXULTemplateBuilder
|
||||
NS_IMETHOD Rebuild();
|
||||
|
||||
NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument);
|
||||
|
||||
protected:
|
||||
|
@ -119,6 +116,9 @@ protected:
|
|||
virtual nsresult
|
||||
InitializeRuleNetworkForSimpleRules(InnerNode** aChildNode);
|
||||
|
||||
virtual nsresult
|
||||
RebuildAll();
|
||||
|
||||
/**
|
||||
* Override default behavior to additionally handle the <row>
|
||||
* condition.
|
||||
|
@ -407,60 +407,66 @@ nsXULTreeBuilder::Sort(nsIDOMElement* aElement)
|
|||
if (! header)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsAutoString sortLocked;
|
||||
header->GetAttr(kNameSpaceID_None, nsXULAtoms::sortLocked, sortLocked);
|
||||
if (sortLocked.Equals(NS_LITERAL_STRING("true")))
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString sort;
|
||||
header->GetAttr(kNameSpaceID_None, nsXULAtoms::sort, sort);
|
||||
|
||||
if (!sort.IsEmpty()) {
|
||||
// Grab the new sort variable
|
||||
mSortVariable = mRules.LookupSymbol(sort.get());
|
||||
if (sort.IsEmpty())
|
||||
return NS_OK;
|
||||
|
||||
// Cycle the sort direction
|
||||
nsAutoString dir;
|
||||
header->GetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection, dir);
|
||||
// Grab the new sort variable
|
||||
mSortVariable = mRules.LookupSymbol(sort.get());
|
||||
|
||||
if (dir == NS_LITERAL_STRING("ascending")) {
|
||||
dir = NS_LITERAL_STRING("descending");
|
||||
mSortDirection = eDirection_Descending;
|
||||
}
|
||||
else if (dir == NS_LITERAL_STRING("descending")) {
|
||||
dir = NS_LITERAL_STRING("natural");
|
||||
mSortDirection = eDirection_Natural;
|
||||
}
|
||||
else {
|
||||
dir = NS_LITERAL_STRING("ascending");
|
||||
mSortDirection = eDirection_Ascending;
|
||||
}
|
||||
// Cycle the sort direction
|
||||
nsAutoString dir;
|
||||
header->GetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection, dir);
|
||||
|
||||
// Sort it
|
||||
SortSubtree(mRows.GetRoot());
|
||||
mRows.InvalidateCachedRow();
|
||||
if (mBoxObject)
|
||||
mBoxObject->Invalidate();
|
||||
if (dir == NS_LITERAL_STRING("ascending")) {
|
||||
dir = NS_LITERAL_STRING("descending");
|
||||
mSortDirection = eDirection_Descending;
|
||||
}
|
||||
else if (dir == NS_LITERAL_STRING("descending")) {
|
||||
dir = NS_LITERAL_STRING("natural");
|
||||
mSortDirection = eDirection_Natural;
|
||||
}
|
||||
else {
|
||||
dir = NS_LITERAL_STRING("ascending");
|
||||
mSortDirection = eDirection_Ascending;
|
||||
}
|
||||
|
||||
header->SetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection, dir, PR_TRUE);
|
||||
header->SetAttr(kNameSpaceID_None, nsXULAtoms::sortActive, NS_LITERAL_STRING("true"), PR_TRUE);
|
||||
// Sort it.
|
||||
SortSubtree(mRows.GetRoot());
|
||||
mRows.InvalidateCachedRow();
|
||||
if (mBoxObject)
|
||||
mBoxObject->Invalidate();
|
||||
|
||||
// Unset sort attribute(s) on the other columns
|
||||
nsCOMPtr<nsIContent> parentContent;
|
||||
header->GetParent(*getter_AddRefs(parentContent));
|
||||
if (parentContent) {
|
||||
nsCOMPtr<nsIAtom> parentTag;
|
||||
parentContent->GetTag(*getter_AddRefs(parentTag));
|
||||
if (parentTag == nsXULAtoms::treecols) {
|
||||
PRInt32 numChildren;
|
||||
parentContent->ChildCount(numChildren);
|
||||
for (int i = 0; i < numChildren; ++i) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
nsCOMPtr<nsIAtom> childTag;
|
||||
parentContent->ChildAt(i, *getter_AddRefs(childContent));
|
||||
if (childContent) {
|
||||
childContent->GetTag(*getter_AddRefs(childTag));
|
||||
if (childTag == nsXULAtoms::treecol && childContent != header) {
|
||||
childContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsXULAtoms::sortDirection, PR_TRUE);
|
||||
childContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsXULAtoms::sortActive, PR_TRUE);
|
||||
}
|
||||
header->SetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection, dir, PR_TRUE);
|
||||
header->SetAttr(kNameSpaceID_None, nsXULAtoms::sortActive, NS_LITERAL_STRING("true"), PR_TRUE);
|
||||
|
||||
// Unset sort attribute(s) on the other columns
|
||||
nsCOMPtr<nsIContent> parentContent;
|
||||
header->GetParent(*getter_AddRefs(parentContent));
|
||||
if (parentContent) {
|
||||
nsCOMPtr<nsIAtom> parentTag;
|
||||
parentContent->GetTag(*getter_AddRefs(parentTag));
|
||||
if (parentTag == nsXULAtoms::treecols) {
|
||||
PRInt32 numChildren;
|
||||
parentContent->ChildCount(numChildren);
|
||||
for (int i = 0; i < numChildren; ++i) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
nsCOMPtr<nsIAtom> childTag;
|
||||
parentContent->ChildAt(i, *getter_AddRefs(childContent));
|
||||
if (childContent) {
|
||||
childContent->GetTag(*getter_AddRefs(childTag));
|
||||
if (childTag == nsXULAtoms::treecol && childContent != header) {
|
||||
childContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsXULAtoms::sortDirection, PR_TRUE);
|
||||
childContent->UnsetAttr(kNameSpaceID_None,
|
||||
nsXULAtoms::sortActive, PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1051,56 +1057,6 @@ nsXULTreeBuilder::PerformActionOnCell(const PRUnichar* action, PRInt32 row, cons
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsIXULTemplateBuilder methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeBuilder::Rebuild()
|
||||
{
|
||||
NS_PRECONDITION(mRoot != nsnull, "not initialized");
|
||||
if (! mRoot)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count = mRows.Count();
|
||||
mRows.Clear();
|
||||
mConflictSet.Clear();
|
||||
if (mBoxObject)
|
||||
mBoxObject->RowCountChanged(0, -count);
|
||||
|
||||
rv = CompileRules();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Seed the rule network with assignments for the tree row
|
||||
// variable
|
||||
nsCOMPtr<nsIRDFResource> root;
|
||||
nsXULContentUtils::GetElementRefResource(mRoot, getter_AddRefs(root));
|
||||
mRows.SetRootResource(root);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
|
||||
const char* s = "(null)";
|
||||
if (root)
|
||||
root->GetValueConst(&s);
|
||||
|
||||
PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
|
||||
("xultemplate[%p] root=%s", this, s));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (root)
|
||||
OpenContainer(-1, root);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTemplateBuilder abstract methods
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeBuilder::DocumentWillBeDestroyed(nsIDocument* aDocument)
|
||||
|
@ -1371,6 +1327,58 @@ nsXULTreeBuilder::InitializeRuleNetworkForSimpleRules(InnerNode** aChildNode)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULTreeBuilder::RebuildAll()
|
||||
{
|
||||
NS_PRECONDITION(mRoot != nsnull, "not initialized");
|
||||
if (! mRoot)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsresult rv = mRoot->GetDocument(*getter_AddRefs(doc));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Bail out early if we are being torn down.
|
||||
if (!doc)
|
||||
return NS_OK;
|
||||
|
||||
if (mBoxObject) {
|
||||
mBoxObject->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
mRows.Clear();
|
||||
mConflictSet.Clear();
|
||||
|
||||
rv = CompileRules();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Seed the rule network with assignments for the tree row
|
||||
// variable
|
||||
nsCOMPtr<nsIRDFResource> root;
|
||||
nsXULContentUtils::GetElementRefResource(mRoot, getter_AddRefs(root));
|
||||
mRows.SetRootResource(root);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
|
||||
const char* s = "(null)";
|
||||
if (root)
|
||||
root->GetValueConst(&s);
|
||||
|
||||
PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
|
||||
("xultemplate[%p] root=%s", this, s));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (root)
|
||||
OpenContainer(-1, root);
|
||||
|
||||
if (mBoxObject) {
|
||||
mBoxObject->EndUpdateBatch();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULTreeBuilder::CompileCondition(nsIAtom* aTag,
|
||||
nsTemplateRule* aRule,
|
||||
|
|
|
@ -859,29 +859,29 @@ nsLDAPDataSource.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
beginUpdateBatch: function()
|
||||
onBeginUpdateBatch: function()
|
||||
{
|
||||
if (DEBUG) {
|
||||
dump("BeginUpdateBatch() called\n\n");
|
||||
dump("onBeginUpdateBatch() called\n\n");
|
||||
}
|
||||
|
||||
var iter = new ArrayEnumerator(this.mObserverList);
|
||||
var nextObserver;
|
||||
while ((nextObserver = iter.getNext()) != null) {
|
||||
nextObserver.beginUpdateBatch(this);
|
||||
nextObserver.onBeginUpdateBatch(this);
|
||||
}
|
||||
},
|
||||
|
||||
endUpdateBatch: function()
|
||||
onEndUpdateBatch: function()
|
||||
{
|
||||
if (DEBUG) {
|
||||
dump("EndUpdateBatch() called\n\n");
|
||||
dump("onEndUpdateBatch() called\n\n");
|
||||
}
|
||||
|
||||
var iter = new ArrayEnumerator(this.mObserverList);
|
||||
var nextObserver;
|
||||
while ((nextObserver = iter.getNext()) != null) {
|
||||
nextObserver.endUpdateBatch(this);
|
||||
nextObserver.onEndUpdateBatch(this);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -581,6 +581,24 @@ mozSqlResult::DoCommand(nsISupportsArray* aSources,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozSqlResult::BeginUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
mObservers[i]->OnBeginUpdateBatch(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozSqlResult::EndUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
mObservers[i]->OnEndUpdateBatch(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozSqlResult::GetLoaded(PRBool* aResult)
|
||||
|
|
|
@ -551,6 +551,18 @@ mozSqlService::DoCommand(nsISupportsArray* aSources,
|
|||
return mInner->DoCommand(aSources, aCommand, aArguments);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozSqlService::BeginUpdateBatch()
|
||||
{
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
mozSqlService::EndUpdateBatch()
|
||||
{
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
||||
|
||||
// nsIRDFRemoteDataSource
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -173,6 +173,19 @@ interface nsITreeBoxObject : nsISupports
|
|||
*/
|
||||
void rowCountChanged(in long index, in long count);
|
||||
|
||||
/**
|
||||
* Notify the tree that the view is about to perform a batch
|
||||
* update, that is, add, remove or invalidate several rows at once.
|
||||
* This must be followed by calling endUpdateBatch(), otherwise the tree
|
||||
* will get out of sync.
|
||||
*/
|
||||
void beginUpdateBatch();
|
||||
|
||||
/**
|
||||
* Notify the tree that the view has completed a batch update.
|
||||
*/
|
||||
void endUpdateBatch();
|
||||
|
||||
/**
|
||||
* Drag handlers, installed from XBL, called when drags occur to handle painting
|
||||
*/
|
||||
|
|
|
@ -335,7 +335,8 @@ nsTreeBodyFrame::nsTreeBodyFrame(nsIPresShell* aPresShell)
|
|||
mColumns(nsnull), mScrollbar(nsnull), mTopRowIndex(0), mRowHeight(0), mIndentation(0), mStringWidth(-1),
|
||||
mFocused(PR_FALSE), mColumnsDirty(PR_TRUE), mDropAllowed(PR_FALSE), mHasFixedRowCount(PR_FALSE),
|
||||
mVerticalOverflow(PR_FALSE), mImageGuard(PR_FALSE), mReflowCallbackPosted(PR_FALSE),
|
||||
mDropRow(-1), mDropOrient(-1), mScrollLines(0), mTimer(nsnull), mValueArray(~PRInt32(0))
|
||||
mDropRow(-1), mDropOrient(-1), mScrollLines(0), mTimer(nsnull), mValueArray(~PRInt32(0)),
|
||||
mUpdateBatchNest(0), mCountBeforeUpdate(-1)
|
||||
{
|
||||
NS_NewISupportsArray(getter_AddRefs(mScratchArray));
|
||||
}
|
||||
|
@ -886,6 +887,8 @@ NS_IMETHODIMP nsTreeBodyFrame::GetPageCount(PRInt32 *_retval)
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::Invalidate()
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
if (!mRect.IsEmpty()) {
|
||||
nsLeafBoxFrame::Invalidate(mPresContext, mRect, PR_FALSE);
|
||||
}
|
||||
|
@ -894,6 +897,8 @@ NS_IMETHODIMP nsTreeBodyFrame::Invalidate()
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::InvalidateColumn(const PRUnichar *aColID)
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
nscoord currX = mInnerBox.x;
|
||||
for (nsTreeColumn* currCol = mColumns; currCol && currX < mInnerBox.x+mInnerBox.width;
|
||||
currCol = currCol->GetNext()) {
|
||||
|
@ -910,6 +915,8 @@ NS_IMETHODIMP nsTreeBodyFrame::InvalidateColumn(const PRUnichar *aColID)
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::InvalidateRow(PRInt32 aIndex)
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
if (aIndex < mTopRowIndex || aIndex > mTopRowIndex + mPageCount + 1)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -921,6 +928,8 @@ NS_IMETHODIMP nsTreeBodyFrame::InvalidateRow(PRInt32 aIndex)
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::InvalidateCell(PRInt32 aIndex, const PRUnichar *aColID)
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
if (aIndex < mTopRowIndex || aIndex > mTopRowIndex + mPageCount + 1)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -944,6 +953,8 @@ NS_IMETHODIMP nsTreeBodyFrame::InvalidateCell(PRInt32 aIndex, const PRUnichar *a
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::InvalidatePrimaryCell(PRInt32 aIndex)
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
if (aIndex < mTopRowIndex || aIndex > mTopRowIndex + mPageCount + 1)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -970,6 +981,8 @@ NS_IMETHODIMP nsTreeBodyFrame::InvalidatePrimaryCell(PRInt32 aIndex)
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::InvalidateRange(PRInt32 aStart, PRInt32 aEnd)
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
if (aStart == aEnd)
|
||||
return InvalidateRow(aStart);
|
||||
|
||||
|
@ -1058,6 +1071,8 @@ nsresult nsTreeBodyFrame::CheckVerticalOverflow()
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::InvalidateScrollbar()
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
if (!EnsureScrollbar() || !mView)
|
||||
return NS_OK;
|
||||
|
||||
|
@ -1695,6 +1710,9 @@ nsTreeBodyFrame::CreateTimer(const nsILookAndFeel::nsMetricID aID,
|
|||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
|
||||
{
|
||||
if (mUpdateBatchNest)
|
||||
return NS_OK;
|
||||
|
||||
if (aCount == 0 || !mView)
|
||||
return NS_OK; // Nothing to do.
|
||||
|
||||
|
@ -1738,9 +1756,10 @@ NS_IMETHODIMP nsTreeBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
|
|||
}
|
||||
else if (mTopRowIndex >= aIndex) {
|
||||
// This is a full-blown invalidate.
|
||||
if (mTopRowIndex + mPageCount > rowCount - 1)
|
||||
if (mTopRowIndex + mPageCount > rowCount - 1) {
|
||||
mTopRowIndex = PR_MAX(0, rowCount - 1 - mPageCount);
|
||||
UpdateScrollbar();
|
||||
UpdateScrollbar();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
@ -1752,6 +1771,40 @@ NS_IMETHODIMP nsTreeBodyFrame::RowCountChanged(PRInt32 aIndex, PRInt32 aCount)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::BeginUpdateBatch()
|
||||
{
|
||||
if (mUpdateBatchNest++ == 0) {
|
||||
if (mView) {
|
||||
mView->GetRowCount(&mCountBeforeUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeBodyFrame::EndUpdateBatch()
|
||||
{
|
||||
NS_ASSERTION(mUpdateBatchNest > 0, "badly nested update batch");
|
||||
|
||||
if (--mUpdateBatchNest == 0) {
|
||||
if (mView) {
|
||||
Invalidate();
|
||||
PRInt32 countAfterUpdate;
|
||||
mView->GetRowCount(&countAfterUpdate);
|
||||
if (mCountBeforeUpdate != countAfterUpdate) {
|
||||
if (mTopRowIndex + mPageCount > countAfterUpdate - 1) {
|
||||
mTopRowIndex = PR_MAX(0, countAfterUpdate - 1 - mPageCount);
|
||||
UpdateScrollbar();
|
||||
}
|
||||
InvalidateScrollbar();
|
||||
CheckVerticalOverflow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeBodyFrame::PrefillPropertyArray(PRInt32 aRowIndex, nsTreeColumn* aCol)
|
||||
{
|
||||
|
|
|
@ -526,6 +526,8 @@ protected: // Data Members
|
|||
|
||||
PRPackedBool mVerticalOverflow;
|
||||
|
||||
PRInt16 mUpdateBatchNest;
|
||||
|
||||
// A guard that prevents us from recursive painting.
|
||||
PRPackedBool mImageGuard;
|
||||
|
||||
|
@ -548,4 +550,6 @@ protected: // Data Members
|
|||
// A value array used to keep track of all spring loaded folders.
|
||||
nsValueArray mValueArray;
|
||||
|
||||
PRInt32 mCountBeforeUpdate;
|
||||
|
||||
}; // class nsTreeBodyFrame
|
||||
|
|
|
@ -424,6 +424,22 @@ NS_IMETHODIMP nsTreeBoxObject::RowCountChanged(PRInt32 aIndex, PRInt32 aDelta)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeBoxObject::BeginUpdateBatch()
|
||||
{
|
||||
nsITreeBoxObject* body = GetTreeBody();
|
||||
if (body)
|
||||
return body->BeginUpdateBatch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeBoxObject::EndUpdateBatch()
|
||||
{
|
||||
nsITreeBoxObject* body = GetTreeBody();
|
||||
if (body)
|
||||
return body->EndUpdateBatch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeBoxObject::OnDragEnter(nsIDOMEvent* inEvent)
|
||||
{
|
||||
nsITreeBoxObject* body = GetTreeBody();
|
||||
|
|
|
@ -523,3 +523,14 @@ NS_IMETHODIMP nsAbRDFDataSource::DoCommand
|
|||
return NS_RDF_NO_VALUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbRDFDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAbRDFDataSource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -308,6 +308,20 @@ nsMsgRDFDataSource::DoCommand(nsISupportsArray *aSources, nsIRDFResource *aComma
|
|||
return NS_RDF_NO_VALUE;
|
||||
}
|
||||
|
||||
/* void BeginUpdateBatch (); */
|
||||
NS_IMETHODIMP
|
||||
nsMsgRDFDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void EndUpdateBatch (); */
|
||||
NS_IMETHODIMP
|
||||
nsMsgRDFDataSource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* XPCOM Shutdown observer */
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -582,3 +582,15 @@ nsSoundDatasource::RemoveObserver(nsIRDFObserver *n)
|
|||
mObservers->RemoveElement(n);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSoundDatasource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSoundDatasource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -724,6 +724,24 @@ nsSubscribeDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|||
return(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSubscribeDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSubscribeDataSource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSubscribeDataSource::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, PRBool aTruthValue, nsISimpleEnumerator **_retval)
|
||||
{
|
||||
|
|
|
@ -422,3 +422,15 @@ NS_IMETHODIMP nsSmtpDataSource::GetAllCmds(nsIRDFResource *aSource, nsISimpleEnu
|
|||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* void beginUpdateBatch (); */
|
||||
NS_IMETHODIMP nsSmtpDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void endUpdateBatch (); */
|
||||
NS_IMETHODIMP nsSmtpDataSource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -235,9 +235,8 @@ pref("browser.fixup.alternate.enabled", true);
|
|||
pref("browser.fixup.alternate.prefix", "www.");
|
||||
pref("browser.fixup.alternate.suffix", ".com");
|
||||
|
||||
// Default bookmark sorting
|
||||
pref("browser.bookmarks.sort.direction", "descending");
|
||||
pref("browser.bookmarks.sort.resource", "rdf:http://home.netscape.com/NC-rdf#Name");
|
||||
// Bookmarks prefs
|
||||
pref("browser.bookmarks.confirm_sorting", true);
|
||||
|
||||
//Internet Search
|
||||
pref("browser.search.defaultenginename", "chrome://communicator-region/locale/region.properties");
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
nsIRDFCompositeDataSource.idl
|
||||
nsIRDFContainer.idl
|
||||
nsIRDFContainerUtils.idl
|
||||
nsIRDFDataSource.idl
|
||||
nsIRDFLiteral.idl
|
||||
nsIRDFNode.idl
|
||||
nsIRDFObserver.idl
|
||||
nsIRDFInMemoryDataSource.idl
|
||||
nsIRDFPurgeableDataSource.idl
|
||||
nsIRDFRemoteDataSource.idl
|
||||
nsIRDFResource.idl
|
||||
nsIRDFService.idl
|
||||
nsIRDFXMLParser.idl
|
||||
nsIRDFXMLSerializer.idl
|
||||
nsIRDFXMLSink.idl
|
||||
nsIRDFXMLSource.idl
|
|
@ -39,6 +39,7 @@ XPIDLSRCS = \
|
|||
nsIRDFNode.idl \
|
||||
nsIRDFObserver.idl \
|
||||
nsIRDFInMemoryDataSource.idl \
|
||||
nsIRDFPropagatableDataSource.idl \
|
||||
nsIRDFPurgeableDataSource.idl \
|
||||
nsIRDFRemoteDataSource.idl \
|
||||
nsIRDFResource.idl \
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jan Varga <varga@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -217,5 +218,18 @@ interface nsIRDFDataSource : nsISupports
|
|||
* Equivalent to enumerating ArcLabelsOut and comparing for the specified arc.
|
||||
*/
|
||||
boolean hasArcOut(in nsIRDFResource aSource, in nsIRDFResource aArc);
|
||||
};
|
||||
|
||||
/**
|
||||
* Notify observers that the datasource is about to send several
|
||||
* notifications at once.
|
||||
* This must be followed by calling endUpdateBatch(), otherwise
|
||||
* viewers will get out of sync.
|
||||
*/
|
||||
void beginUpdateBatch();
|
||||
|
||||
/**
|
||||
* Notify observers that the datasource has completed issuing
|
||||
* a notification group.
|
||||
*/
|
||||
void endUpdateBatch();
|
||||
};
|
||||
|
|
|
@ -114,7 +114,7 @@ interface nsIRDFObserver : nsISupports {
|
|||
* @param aDataSource the datasource that is going to
|
||||
* be issuing the notifications.
|
||||
*/
|
||||
void beginUpdateBatch(in nsIRDFDataSource aDataSource);
|
||||
void onBeginUpdateBatch(in nsIRDFDataSource aDataSource);
|
||||
|
||||
/**
|
||||
* This method is called when a datasource has completed
|
||||
|
@ -122,7 +122,5 @@ interface nsIRDFObserver : nsISupports {
|
|||
* @param aDataSource the datasource that has finished
|
||||
* issuing a group of notifications
|
||||
*/
|
||||
void endUpdateBatch(in nsIRDFDataSource aDataSource);
|
||||
void onEndUpdateBatch(in nsIRDFDataSource aDataSource);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corp.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jan Varga <varga@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* An nsIRDFPropagatableDataSource provides an ability to suppress
|
||||
* synchronization notifications.
|
||||
*/
|
||||
[scriptable, uuid(5a9b4770-9fcb-4307-a12e-4b6708e78b97)]
|
||||
interface nsIRDFPropagatableDataSource: nsISupports {
|
||||
|
||||
/**
|
||||
* Set this value to <code>true</code> to enable synchronization
|
||||
* notifications.
|
||||
*
|
||||
* Set this value to <code>false</code> to disable synchronization
|
||||
* notifications.
|
||||
*
|
||||
* By default, this value is <code>true</code>.
|
||||
*/
|
||||
attribute boolean propagateChanges;
|
||||
|
||||
};
|
|
@ -32,10 +32,8 @@ REQUIRES = xpcom \
|
|||
string \
|
||||
rdfutil \
|
||||
necko \
|
||||
layout \
|
||||
content \
|
||||
htmlparser \
|
||||
js \
|
||||
unicharutil \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -1343,6 +1343,24 @@ CompositeDataSourceImpl::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSource
|
|||
return(NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::BeginUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
|
||||
mDataSources[i]->BeginUpdateBatch();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::EndUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
|
||||
mDataSources[i]->EndUpdateBatch();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFCompositeDataSource methods
|
||||
// XXX rvg We should make this take an additional argument specifying where
|
||||
|
@ -1443,7 +1461,6 @@ CompositeDataSourceImpl::OnAssert(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnAssert(this, aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1475,7 +1492,6 @@ CompositeDataSourceImpl::OnUnassert(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnUnassert(this, aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1497,7 +1513,6 @@ CompositeDataSourceImpl::OnChange(nsIRDFDataSource* aDataSource,
|
|||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnChange(this, aSource, aProperty,
|
||||
aOldTarget, aNewTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1519,20 +1534,17 @@ CompositeDataSourceImpl::OnMove(nsIRDFDataSource* aDataSource,
|
|||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnMove(this, aOldSource, aNewSource,
|
||||
aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
CompositeDataSourceImpl::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
PRInt32 nest = mUpdateBatchNest++;
|
||||
if (nest == 0) {
|
||||
if (mUpdateBatchNest++ == 0) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
mObservers[i]->BeginUpdateBatch(this);
|
||||
// XXX ignore return value?
|
||||
mObservers[i]->OnBeginUpdateBatch(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
@ -1540,18 +1552,12 @@ CompositeDataSourceImpl::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
CompositeDataSourceImpl::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
CompositeDataSourceImpl::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
PRInt32 nest = --mUpdateBatchNest;
|
||||
if (nest < 0) {
|
||||
NS_ERROR("badly nested update batch");
|
||||
mUpdateBatchNest = 0;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (nest == 0) {
|
||||
NS_ASSERTION(mUpdateBatchNest > 0, "badly nested update batch");
|
||||
if (--mUpdateBatchNest == 0) {
|
||||
for (PRInt32 i = mObservers.Count() - 1; i >= 0; --i) {
|
||||
mObservers[i]->EndUpdateBatch(this);
|
||||
// XXX ignore return value?
|
||||
mObservers[i]->OnEndUpdateBatch(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFInMemoryDataSource.h"
|
||||
#include "nsIRDFPropagatableDataSource.h"
|
||||
#include "nsIRDFPurgeableDataSource.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
@ -283,6 +284,7 @@ class InMemoryResourceEnumeratorImpl;
|
|||
|
||||
class InMemoryDataSource : public nsIRDFDataSource,
|
||||
public nsIRDFInMemoryDataSource,
|
||||
public nsIRDFPropagatableDataSource,
|
||||
public nsIRDFPurgeableDataSource
|
||||
{
|
||||
protected:
|
||||
|
@ -339,6 +341,9 @@ public:
|
|||
// nsIRDFInMemoryDataSource methods
|
||||
NS_DECL_NSIRDFINMEMORYDATASOURCE
|
||||
|
||||
// nsIRDFPropagatableDataSource methods
|
||||
NS_DECL_NSIRDFPROPAGATABLEDATASOURCE
|
||||
|
||||
// nsIRDFPurgeableDataSource methods
|
||||
NS_DECL_NSIRDFPURGEABLEDATASOURCE
|
||||
|
||||
|
@ -396,6 +401,7 @@ public:
|
|||
// This datasource's monitor object.
|
||||
PRLock* mLock;
|
||||
#endif
|
||||
PRBool mPropagateChanges;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -885,6 +891,7 @@ InMemoryDataSource::InMemoryDataSource(nsISupports* aOuter)
|
|||
#ifdef MOZ_THREADSAFE_RDF
|
||||
mLock = nsnull;
|
||||
#endif
|
||||
mPropagateChanges = PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -982,6 +989,9 @@ InMemoryDataSource::AggregatedQueryInterface(REFNSIID aIID, void** aResult)
|
|||
else if (aIID.Equals(NS_GET_IID(nsIRDFInMemoryDataSource))) {
|
||||
*aResult = NS_STATIC_CAST(nsIRDFInMemoryDataSource*, this);
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsIRDFPropagatableDataSource))) {
|
||||
*aResult = NS_STATIC_CAST(nsIRDFPropagatableDataSource*, this);
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsIRDFPurgeableDataSource))) {
|
||||
*aResult = NS_STATIC_CAST(nsIRDFPurgeableDataSource*, this);
|
||||
}
|
||||
|
@ -1389,7 +1399,7 @@ InMemoryDataSource::Assert(nsIRDFResource* aSource,
|
|||
}
|
||||
|
||||
// notify observers
|
||||
for (PRInt32 i = (PRInt32)mNumObservers - 1; i >= 0; --i) {
|
||||
for (PRInt32 i = (PRInt32)mNumObservers - 1; mPropagateChanges && i >= 0; --i) {
|
||||
nsIRDFObserver* obs = mObservers[i];
|
||||
|
||||
// XXX this should never happen, but it does, and we can't figure out why.
|
||||
|
@ -1541,7 +1551,7 @@ InMemoryDataSource::Unassert(nsIRDFResource* aSource,
|
|||
}
|
||||
|
||||
// Notify the world
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; i >= 0; --i) {
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
|
||||
nsIRDFObserver* obs = mObservers[i];
|
||||
|
||||
// XXX this should never happen, but it does, and we can't figure out why.
|
||||
|
@ -1595,7 +1605,7 @@ InMemoryDataSource::Change(nsIRDFResource* aSource,
|
|||
}
|
||||
|
||||
// Notify the world
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; i >= 0; --i) {
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
|
||||
nsIRDFObserver* obs = mObservers[i];
|
||||
|
||||
// XXX this should never happen, but it does, and we can't figure out why.
|
||||
|
@ -1649,7 +1659,7 @@ InMemoryDataSource::Move(nsIRDFResource* aOldSource,
|
|||
}
|
||||
|
||||
// Notify the world
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; i >= 0; --i) {
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
|
||||
nsIRDFObserver* obs = mObservers[i];
|
||||
|
||||
// XXX this should never happen, but it does, and we can't figure out why.
|
||||
|
@ -1843,6 +1853,27 @@ InMemoryDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InMemoryDataSource::BeginUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
|
||||
nsIRDFObserver* obs = mObservers[i];
|
||||
obs->OnBeginUpdateBatch(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InMemoryDataSource::EndUpdateBatch()
|
||||
{
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
|
||||
nsIRDFObserver* obs = mObservers[i];
|
||||
obs->OnEndUpdateBatch(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFInMemoryDataSource methods
|
||||
|
@ -1899,6 +1930,23 @@ InMemoryDataSource::EnsureFastContainment(nsIRDFResource* aSource)
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFPropagatableDataSource methods
|
||||
NS_IMETHODIMP
|
||||
InMemoryDataSource::GetPropagateChanges(PRBool* aPropagateChanges)
|
||||
{
|
||||
*aPropagateChanges = mPropagateChanges;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InMemoryDataSource::SetPropagateChanges(PRBool aPropagateChanges)
|
||||
{
|
||||
mPropagateChanges = aPropagateChanges;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFPurgeableDataSource methods
|
||||
|
||||
|
@ -1999,7 +2047,7 @@ InMemoryDataSource::Sweep()
|
|||
#endif
|
||||
if (!(as->mHashEntry))
|
||||
{
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; i >= 0; --i) {
|
||||
for (PRInt32 i = PRInt32(mNumObservers) - 1; mPropagateChanges && i >= 0; --i) {
|
||||
nsIRDFObserver* obs = mObservers[i];
|
||||
// XXXbz other loops over mObservers null-check |obs| here!
|
||||
obs->OnUnassert(this, as->mSource, as->u.as.mProperty, as->u.as.mTarget);
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFInMemoryDataSource.h"
|
||||
#include "nsIRDFPropagatableDataSource.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
|
@ -542,16 +543,12 @@ RDFContainerImpl::Renumber(PRInt32 aStartIndex, PRInt32 aIncrement)
|
|||
i = count; // we're one-indexed.
|
||||
}
|
||||
|
||||
// Note: once we begin batch updates, don't exit this method until
|
||||
// ending batch updates, otherwise viewers will get out of sync
|
||||
nsCOMPtr<nsIRDFObserver> dsObs;
|
||||
if (mDataSource)
|
||||
{
|
||||
dsObs = do_QueryInterface(mDataSource);
|
||||
if (dsObs)
|
||||
{
|
||||
dsObs->BeginUpdateBatch(mDataSource);
|
||||
}
|
||||
// Note: once we disable notifications, don't exit this method until
|
||||
// enabling notifications
|
||||
nsCOMPtr<nsIRDFPropagatableDataSource> propagatable =
|
||||
do_QueryInterface(mDataSource);
|
||||
if (propagatable) {
|
||||
propagatable->SetPropagateChanges(PR_FALSE);
|
||||
}
|
||||
|
||||
PRBool err = PR_FALSE;
|
||||
|
@ -647,9 +644,10 @@ RDFContainerImpl::Renumber(PRInt32 aStartIndex, PRInt32 aIncrement)
|
|||
}
|
||||
}
|
||||
|
||||
// Note: MUST end update batching before exiting this method
|
||||
// otherwise viewers will get out of sync
|
||||
if (dsObs) dsObs->EndUpdateBatch(mDataSource);
|
||||
// Note: MUST enable notifications before exiting this method
|
||||
if (propagatable) {
|
||||
propagatable->SetPropagateChanges(PR_TRUE);
|
||||
}
|
||||
|
||||
if (err == PR_TRUE) return(rv);
|
||||
|
||||
|
@ -771,5 +769,3 @@ RDFContainerImpl::GetNextValue(nsIRDFResource** aResult)
|
|||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -450,11 +450,7 @@ RDFContainerUtilsImpl::MakeContainer(nsIRDFDataSource* aDataSource, nsIRDFResour
|
|||
rv = aDataSource->Assert(aResource, kRDF_instanceOf, aType, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> nextVal;
|
||||
rv = gRDFService->GetLiteral(NS_LITERAL_STRING("1").get(), getter_AddRefs(nextVal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aDataSource->Assert(aResource, kRDF_nextVal, nextVal, PR_TRUE);
|
||||
rv = aDataSource->Assert(aResource, kRDF_nextVal, kOne, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,11 +45,9 @@
|
|||
*/
|
||||
|
||||
#include <stdlib.h> // XXX for atoi(), maybe this should go into nsCRT?
|
||||
#include "nsCRT.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsString.h"
|
||||
#include "nsRDFParserUtils.h"
|
||||
#include "jsapi.h" // for JSVERSION_* and JS_VersionToString
|
||||
|
||||
// XXX This totally sucks. I wish that mozilla/base had this code.
|
||||
PRUnichar
|
||||
|
|
|
@ -45,11 +45,6 @@
|
|||
#ifndef nsRDFParserUtils_h__
|
||||
#define nsRDFParserUtils_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "jspubtd.h"
|
||||
class nsIURI;
|
||||
class nsString;
|
||||
|
||||
class nsRDFParserUtils {
|
||||
public:
|
||||
static PRUnichar
|
||||
|
@ -64,6 +59,4 @@ public:
|
|||
nsString& aValue);
|
||||
};
|
||||
|
||||
|
||||
#endif // nsRDFPasrserUtils_h__
|
||||
|
||||
|
|
|
@ -363,6 +363,14 @@ public:
|
|||
return mInner->DoCommand(aSources, aCommand, aArguments);
|
||||
}
|
||||
|
||||
NS_IMETHOD BeginUpdateBatch() {
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHOD EndUpdateBatch() {
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
||||
// nsIRDFRemoteDataSource interface
|
||||
NS_DECL_NSIRDFREMOTEDATASOURCE
|
||||
|
||||
|
|
|
@ -287,6 +287,16 @@ nsChromeUIDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|||
return mComposite->DoCommand(aSources, aCommand, aArguments);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::BeginUpdateBatch() {
|
||||
return mComposite->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::EndUpdateBatch() {
|
||||
return mComposite->EndUpdateBatch();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -299,7 +309,6 @@ nsChromeUIDataSource::OnAssert(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnAssert(this, aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -313,7 +322,6 @@ nsChromeUIDataSource::OnUnassert(nsIRDFDataSource* aDataSource,
|
|||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnUnassert(aDataSource, aSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -330,7 +338,6 @@ nsChromeUIDataSource::OnChange(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnChange(aDataSource, aSource, aProperty, aOldTarget, aNewTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -347,20 +354,29 @@ nsChromeUIDataSource::OnMove(nsIRDFDataSource* aDataSource,
|
|||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnMove(aDataSource, aOldSource, aNewSource, aProperty, aTarget);
|
||||
// XXX ignore return value?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsChromeUIDataSource::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnBeginUpdateBatch(aDataSource);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsChromeUIDataSource::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsChromeUIDataSource::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
mObservers[i]->OnEndUpdateBatch(aDataSource);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1104,6 +1104,22 @@ FileSystemDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileSystemDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileSystemDataSource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_NewRDFFileSystemDataSource(nsIRDFDataSource **result)
|
||||
{
|
||||
|
|
|
@ -214,6 +214,14 @@ public:
|
|||
nsIRDFResource* aCommand,
|
||||
nsISupportsArray/*<nsIRDFResource>*/* aArguments);
|
||||
|
||||
NS_IMETHOD BeginUpdateBatch() {
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHOD EndUpdateBatch() {
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHOD GetLoaded(PRBool* _result);
|
||||
NS_IMETHOD Init(const char *uri);
|
||||
NS_IMETHOD Flush();
|
||||
|
|
|
@ -105,6 +105,12 @@ class nsRDFDOMDataSource : public nsISupports {
|
|||
|
||||
/* void DoCommand (in nsISupportsArray aSources, in nsIRDFResource aCommand, in nsISupportsArray aArguments); */
|
||||
NS_IMETHOD DoCommand(nsISupportsArray * aSources, nsIRDFResource *aCommand, nsISupportsArray * aArguments) = 0;
|
||||
|
||||
/* void beginUpdateBatch (); */
|
||||
NS_IMETHOD BeginUpdateBatch() = 0;
|
||||
|
||||
/* void endUpdateBatch (); */
|
||||
NS_IMETHOD EndUpdateBatch() = 0;
|
||||
};
|
||||
|
||||
#endif /* __gen_nsRDFDOMDataSource_h__ */
|
||||
|
|
|
@ -120,6 +120,12 @@ public:
|
|||
/* void DoCommand (in nsISupportsArray aSources, in nsIRDFResource aCommand, in nsISupportsArray aArguments); */
|
||||
NS_IMETHOD DoCommand(nsISupportsArray * aSources, nsIRDFResource *aCommand, nsISupportsArray * aArguments);
|
||||
|
||||
/* void beginUpdateBatch (); */
|
||||
NS_IMETHOD BeginUpdateBatch();
|
||||
|
||||
/* void endUpdateBatch (); */
|
||||
NS_IMETHOD EndUpdateBatch();
|
||||
|
||||
private:
|
||||
char *mURI;
|
||||
nsIRDFDataSource* mDataSource;
|
||||
|
@ -446,6 +452,20 @@ nsRDFDataSourceDataSource::DoCommand(nsISupportsArray * aSources, nsIRDFResource
|
|||
return NS_RDF_NO_VALUE;
|
||||
}
|
||||
|
||||
/* void beginUpdateBatch (); */
|
||||
NS_IMETHODIMP
|
||||
nsRDFDataSourceDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void endUpdateBatch (); */
|
||||
NS_IMETHODIMP
|
||||
nsRDFDataSourceDataSource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewRDFDataSourceDataSource(nsISupports *, const nsIID& iid,
|
||||
void ** result)
|
||||
|
|
|
@ -239,13 +239,13 @@ Observer::OnMove(nsIRDFDataSource* aDataSource,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Observer::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
Observer::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Observer::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
Observer::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -63,21 +63,6 @@ interface nsIBrowserHistory : nsISupports
|
|||
*/
|
||||
void removePage(in string aURL);
|
||||
|
||||
/**
|
||||
* startBatchUpdate
|
||||
* Signals the beginning of some kind of batch update (e.g. delete).
|
||||
* Observers won't be notified until there are no batches in progress
|
||||
* (a startBatchUpdate call should always be followed by one to
|
||||
* endBatchUpdate).
|
||||
*/
|
||||
void startBatchUpdate();
|
||||
|
||||
/**
|
||||
* endBatchUpdate
|
||||
* Signals the end of a batch update.
|
||||
*/
|
||||
void endBatchUpdate();
|
||||
|
||||
/**
|
||||
* removePagesFromHost
|
||||
* Remove all pages from the given host.
|
||||
|
|
|
@ -1104,7 +1104,7 @@ nsGlobalHistory::RemoveMatchingRows(rowMatchCallback aMatchFunc,
|
|||
err = mTable->GetCount(mEnv, &count);
|
||||
if (err != 0) return NS_ERROR_FAILURE;
|
||||
|
||||
StartBatchUpdate();
|
||||
BeginUpdateBatch();
|
||||
|
||||
// Begin the batch.
|
||||
int marker;
|
||||
|
@ -1164,7 +1164,7 @@ nsGlobalHistory::RemoveMatchingRows(rowMatchCallback aMatchFunc,
|
|||
err = mTable->EndBatchChangeHint(mEnv, &marker);
|
||||
NS_ASSERTION(err == 0, "error ending batch");
|
||||
|
||||
EndBatchUpdate();
|
||||
EndUpdateBatch();
|
||||
|
||||
return ( err == 0) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2194,6 +2194,66 @@ nsGlobalHistory::GetAllResources(nsISimpleEnumerator** aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::BeginUpdateBatch()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
++mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->OnBeginUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::EndUpdateBatch()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
--mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->OnEndUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2235,66 +2295,6 @@ nsGlobalHistory::FlushTo(const char* aURI)
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::StartBatchUpdate()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
++mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->BeginUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::EndBatchUpdate()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
--mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->EndUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsGlobalHistory
|
||||
|
|
|
@ -626,11 +626,9 @@ function LoadBookmarksCallback()
|
|||
// loads the services
|
||||
initServices();
|
||||
initBMService();
|
||||
var hasRead = BMSVC.readBookmarks();
|
||||
BMSVC.readBookmarks();
|
||||
var bt = document.getElementById("bookmarks-ptf");
|
||||
if (bt) {
|
||||
if (hasRead)
|
||||
bt.builder.rebuild();
|
||||
bt.database.AddObserver(BookmarksToolbarRDFObserver);
|
||||
}
|
||||
window.addEventListener("resize", BookmarksToolbar.resizeFunc, false);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Ben Goodger <ben@netscape.com>
|
||||
* Jan Varga <varga@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -52,8 +53,12 @@ interface nsIBookmarksService : nsISupports
|
|||
const unsigned long BOOKMARK_SEARCH_TYPE = 1;
|
||||
const unsigned long BOOKMARK_FIND_TYPE = 2;
|
||||
|
||||
const long SORT_DESCENDING = -1;
|
||||
const long SORT_ASCENDING = 1;
|
||||
|
||||
boolean readBookmarks();
|
||||
boolean isBookmarked(in string aURL);
|
||||
boolean isBookmarkedResource(in nsIRDFResource aSource);
|
||||
|
||||
void addBookmarkImmediately(in string aURI, in wstring aTitle, in long bmType, in wstring docCharset);
|
||||
|
||||
|
@ -65,6 +70,12 @@ interface nsIBookmarksService : nsISupports
|
|||
nsIRDFResource createGroupInContainer(in wstring aName, in nsIRDFResource aParentFolder,
|
||||
in long aIndex);
|
||||
|
||||
void sortFolder(in nsIRDFResource aFolder,
|
||||
in nsIRDFResource aProperty,
|
||||
in long aDirection,
|
||||
in boolean aFoldersFirst,
|
||||
in boolean aRecurse);
|
||||
|
||||
nsIRDFResource createBookmark(in wstring aName,
|
||||
in string aURL,
|
||||
in wstring aShortcutURL,
|
||||
|
@ -80,6 +91,8 @@ interface nsIBookmarksService : nsISupports
|
|||
|
||||
nsIRDFResource createSeparator();
|
||||
|
||||
nsIRDFResource cloneResource(in nsIRDFResource aSource);
|
||||
|
||||
void updateBookmarkIcon(in string aURL, in wstring aIconURL);
|
||||
void removeBookmarkIcon(in string aURL, in wstring aIconURL);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var NC_NS, RDF_NS, XUL_NS, NC_NS_CMD;
|
||||
var NC_NS, WEB_NS, RDF_NS, XUL_NS, NC_NS_CMD;
|
||||
|
||||
// definition of the services frequently used for bookmarks
|
||||
var kRDFContractID;
|
||||
|
@ -68,10 +68,15 @@ var kWINDOWContractID;
|
|||
var kWINDOWIID;
|
||||
var WINDOWSVC;
|
||||
|
||||
var kDSContractID;
|
||||
var kDSIID;
|
||||
var DS;
|
||||
|
||||
// should be moved in a separate file
|
||||
function initServices()
|
||||
{
|
||||
NC_NS = "http://home.netscape.com/NC-rdf#";
|
||||
WEB_NS = "http://home.netscape.com/WEB-rdf#";
|
||||
RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
|
||||
XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
NC_NS_CMD = NC_NS + "command?cmd=";
|
||||
|
@ -84,7 +89,7 @@ function initServices()
|
|||
|
||||
kRDFCContractID = "@mozilla.org/rdf/container;1";
|
||||
kRDFCIID = Components.interfaces.nsIRDFContainer;
|
||||
RDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
|
||||
RDFC = Components.classes[kRDFCContractID].createInstance(kRDFCIID);
|
||||
|
||||
kRDFCUContractID = "@mozilla.org/rdf/container-utils;1";
|
||||
kRDFCUIID = Components.interfaces.nsIRDFContainerUtils;
|
||||
|
@ -103,6 +108,9 @@ function initServices()
|
|||
kWINDOWIID = Components.interfaces.nsIWindowMediator;
|
||||
WINDOWSVC = Components.classes[kWINDOWContractID].getService(kWINDOWIID);
|
||||
|
||||
kDSContractID = "@mozilla.org/widget/dragservice;1";
|
||||
kDSIID = Components.interfaces.nsIDragService;
|
||||
DS = Components.classes[kDSContractID].getService(kDSIID);
|
||||
}
|
||||
|
||||
function initBMService()
|
||||
|
@ -110,12 +118,8 @@ function initBMService()
|
|||
kBMSVCIID = Components.interfaces.nsIBookmarksService;
|
||||
BMDS = RDF.GetDataSource("rdf:bookmarks");
|
||||
BMSVC = BMDS.QueryInterface(kBMSVCIID);
|
||||
BookmarkInsertTransaction.prototype.RDFC = RDFC;
|
||||
BookmarkInsertTransaction.prototype.BMDS = BMDS;
|
||||
BookmarkRemoveTransaction.prototype.RDFC = RDFC;
|
||||
BookmarkRemoveTransaction.prototype.BMDS = BMDS;
|
||||
BookmarkImportTransaction.prototype.RDFC = RDFC;
|
||||
BookmarkImportTransaction.prototype.BMDS = BMDS;
|
||||
BookmarkTransaction.prototype.RDFC = RDFC;
|
||||
BookmarkTransaction.prototype.BMDS = BMDS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -277,27 +281,27 @@ var BookmarksCommand = {
|
|||
break;
|
||||
case "Bookmark":
|
||||
commands = ["bm_open", "bm_openinnewwindow", "bm_openinnewtab", "bm_separator",
|
||||
"bm_newfolder", "bm_separator",
|
||||
"bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator",
|
||||
"bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator",
|
||||
"bm_rename", "bm_delete", "bm_separator",
|
||||
"bm_properties"];
|
||||
break;
|
||||
case "Folder":
|
||||
commands = ["bm_expandfolder", "bm_managefolder", "bm_separator",
|
||||
"bm_newfolder", "bm_separator",
|
||||
"bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator",
|
||||
"bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator",
|
||||
"bm_rename", "bm_delete", "bm_separator",
|
||||
"bm_properties"];
|
||||
break;
|
||||
case "FolderGroup":
|
||||
commands = ["bm_open", "bm_expandfolder", "bm_separator",
|
||||
"bm_newfolder", "bm_separator",
|
||||
"bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator",
|
||||
"bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator",
|
||||
"bm_rename", "bm_delete", "bm_separator",
|
||||
"bm_properties"];
|
||||
break;
|
||||
case "PersonalToolbarFolder":
|
||||
commands = ["bm_newfolder", "bm_separator",
|
||||
commands = ["bm_newfolder", "bm_sortfolder", "bm_sortfolderbyname", "bm_separator",
|
||||
"bm_cut", "bm_copy", "bm_paste", "bm_movebookmark", "bm_separator",
|
||||
"bm_rename", "bm_delete", "bm_separator",
|
||||
"bm_properties"];
|
||||
|
@ -472,10 +476,7 @@ var BookmarksCommand = {
|
|||
// since data are ended by \n, remove the last empty node
|
||||
items.pop();
|
||||
for (var i=0; i<items.length; ++i) {
|
||||
var resource = RDF.GetResource(items[i]);
|
||||
name = BookmarksUtils.getProperty(resource, NC_NS+"Name");
|
||||
url = BookmarksUtils.getProperty(resource, NC_NS+"URL" );
|
||||
items[i] = BookmarksUtils.createBookmark(name, url, null, null);
|
||||
items[i] = RDF.GetResource(items[i]);
|
||||
}
|
||||
break;
|
||||
case "text/x-moz-url":
|
||||
|
@ -493,7 +494,7 @@ var BookmarksCommand = {
|
|||
|
||||
var selection = {item: items, parent:Array(items.length), length: items.length};
|
||||
BookmarksUtils.checkSelection(selection);
|
||||
BookmarksUtils.insertSelection("paste", selection, aTarget, true);
|
||||
BookmarksUtils.insertSelection("paste", selection, aTarget);
|
||||
},
|
||||
|
||||
deleteBookmark: function (aSelection)
|
||||
|
@ -703,8 +704,46 @@ var BookmarksCommand = {
|
|||
var selection = RDF.GetResource("NC:BookmarksRoot");
|
||||
var args = [{ property: NC_NS+"URL", literal: fileName}];
|
||||
this.doBookmarksCommand(selection, NC_NS_CMD+"export", args);
|
||||
}
|
||||
},
|
||||
|
||||
sortFolderByName: function(aSelection)
|
||||
{
|
||||
var folder;
|
||||
var type = aSelection.type[0];
|
||||
if (type == "Bookmark")
|
||||
folder = RDF.GetResource(aSelection.parent[0].Value);
|
||||
else {
|
||||
folder = RDF.GetResource(aSelection.item[0].Value);
|
||||
}
|
||||
var property = RDF.GetResource(NC_NS + "Name");
|
||||
BMDS.sortFolder(folder, property, kBMSVCIID.SORT_ASCENDING, true, false);
|
||||
},
|
||||
|
||||
sortFolder: function(aSelection)
|
||||
{
|
||||
var folder;
|
||||
var type = aSelection.type[0];
|
||||
if (type == "Bookmark")
|
||||
folder = RDF.GetResource(aSelection.parent[0].Value);
|
||||
else {
|
||||
folder = RDF.GetResource(aSelection.item[0].Value);
|
||||
}
|
||||
|
||||
var sortOptions = { accepted : false };
|
||||
openDialog("chrome://communicator/content/bookmarks/sortFolder.xul",
|
||||
"sortFolder",
|
||||
"centerscreen,chrome,dependent,resizable=no,modal=yes",
|
||||
sortOptions);
|
||||
|
||||
if (sortOptions.accepted) {
|
||||
var property = BookmarksUtils.getResource(sortOptions.sortBy);
|
||||
var direction = sortOptions.sortOrder == "ascending"
|
||||
? kBMSVCIID.SORT_ASCENDING : kBMSVCIID.SORT_DESCENDING;
|
||||
var foldersFirst = sortOptions.sortFoldersFirst;
|
||||
var recurse = sortOptions.sortRecursively;
|
||||
BMDS.sortFolder(folder, property, direction, foldersFirst, recurse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -741,6 +780,8 @@ var BookmarksController = {
|
|||
case "cmd_bm_import":
|
||||
case "cmd_bm_export":
|
||||
case "cmd_bm_movebookmark":
|
||||
case "cmd_bm_sortfolderbyname":
|
||||
case "cmd_bm_sortfolder":
|
||||
isCommandSupported = true;
|
||||
break;
|
||||
default:
|
||||
|
@ -753,9 +794,6 @@ var BookmarksController = {
|
|||
|
||||
isCommandEnabled: function (aCommand, aSelection, aTarget)
|
||||
{
|
||||
if (aTarget.parent.Value == "NC:BookmarksTopRoot")
|
||||
return false;
|
||||
|
||||
var item0, type0;
|
||||
var length = aSelection.length;
|
||||
if (length != 0) {
|
||||
|
@ -766,10 +804,11 @@ var BookmarksController = {
|
|||
|
||||
switch(aCommand) {
|
||||
case "cmd_undo":
|
||||
case "cmd_redo":
|
||||
case "cmd_bm_undo":
|
||||
return BMSVC.transactionManager.numberOfUndoItems > 0;
|
||||
case "cmd_redo":
|
||||
case "cmd_bm_redo":
|
||||
return true;
|
||||
return BMSVC.transactionManager.numberOfRedoItems > 0;
|
||||
case "cmd_bm_paste":
|
||||
if (!BookmarksUtils.isValidTargetContainer(aTarget.parent))
|
||||
return false;
|
||||
|
@ -793,8 +832,6 @@ var BookmarksController = {
|
|||
case "cmd_bm_copy":
|
||||
return length > 0;
|
||||
case "cmd_bm_cut":
|
||||
// disabling cut for now since we don't clone folders
|
||||
return false;
|
||||
case "cmd_bm_delete":
|
||||
return length > 0 && aSelection.containsMutable && !aSelection.containsPTF;
|
||||
case "cmd_bm_selectAll":
|
||||
|
@ -815,6 +852,8 @@ var BookmarksController = {
|
|||
return BookmarksUtils.isValidTargetContainer(aTarget.parent);
|
||||
case "cmd_bm_properties":
|
||||
case "cmd_bm_rename":
|
||||
case "cmd_bm_sortfolderbyname":
|
||||
case "cmd_bm_sortfolder":
|
||||
return length == 1;
|
||||
case "cmd_bm_setnewbookmarkfolder":
|
||||
if (length != 1)
|
||||
|
@ -831,7 +870,7 @@ var BookmarksController = {
|
|||
return item0 != "NC:NewSearchFolder" &&
|
||||
(type0 == "Folder" || type0 == "PersonalToolbarFolder");
|
||||
case "cmd_bm_movebookmark":
|
||||
return length > 0;
|
||||
return length > 0 && !aSelection.containsRF;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -905,6 +944,12 @@ var BookmarksController = {
|
|||
case "cmd_bm_export":
|
||||
BookmarksCommand.exportBookmarks();
|
||||
break;
|
||||
case "cmd_bm_sortfolderbyname":
|
||||
BookmarksCommand.sortFolderByName(aSelection);
|
||||
break;
|
||||
case "cmd_bm_sortfolder":
|
||||
BookmarksCommand.sortFolder(aSelection);
|
||||
break;
|
||||
default:
|
||||
dump("Bookmark command "+aCommand+" not handled!\n");
|
||||
}
|
||||
|
@ -919,7 +964,9 @@ var BookmarksController = {
|
|||
"cmd_bm_setpersonaltoolbarfolder",
|
||||
"cmd_bm_setnewbookmarkfolder",
|
||||
"cmd_bm_setnewsearchfolder", "cmd_bm_movebookmark",
|
||||
"cmd_bm_managefolder"];
|
||||
"cmd_bm_managefolder",
|
||||
"cmd_bm_sortfolder", "cmd_bm_sortfolderbyname",
|
||||
"cmd_undo", "cmd_redo", "cmd_bm_undo", "cmd_bm_redo"];
|
||||
for (var i = 0; i < commands.length; ++i) {
|
||||
var enabled = this.isCommandEnabled(commands[i], aSelection, aTarget);
|
||||
var commandNode = document.getElementById(commands[i]);
|
||||
|
@ -1032,6 +1079,17 @@ var BookmarksUtils = {
|
|||
}
|
||||
},
|
||||
|
||||
getResource: function (aName)
|
||||
{
|
||||
if (aName == "LastModifiedDate" ||
|
||||
aName == "LastVisitDate") {
|
||||
return RDF.GetResource(WEB_NS + aName);
|
||||
}
|
||||
else {
|
||||
return RDF.GetResource(NC_NS + aName);
|
||||
}
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Determine the rdf:type property for the given resource.
|
||||
resolveType: function (aResource)
|
||||
|
@ -1103,36 +1161,6 @@ var BookmarksUtils = {
|
|||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Returns a cloned folder a aFolder (with a different uri). folderType and
|
||||
// other properties are recursively dropped except the 'folder group' one.
|
||||
cloneFolder: function (aFolder)
|
||||
{
|
||||
var rName = this.getProperty(aFolder, NC_NS+"Name");
|
||||
var newFolder;
|
||||
if (this.isFolderGroup(aFolder))
|
||||
newFolder = BMSVC.createGroup(rName);
|
||||
else
|
||||
newFolder = BMSVC.createFolder(rName);
|
||||
|
||||
// Now need to append kiddies.
|
||||
try {
|
||||
RDFC.Init(BMDS, aFolder);
|
||||
var elts = RDFC.GetElements();
|
||||
RDFC.Init(BMDS, newFolder);
|
||||
|
||||
while (elts.hasMoreElements()) {
|
||||
var curr = elts.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
|
||||
if (RDFCU.IsContainer(BMDS, curr))
|
||||
curr = BookmarksUtils.cloneFolder(curr);
|
||||
RDFC.AppendElement(curr);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
return newFolder;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Caches frequently used informations about the selection
|
||||
|
@ -1148,6 +1176,7 @@ var BookmarksUtils = {
|
|||
aSelection.isValid = new Array(aSelection.length);
|
||||
aSelection.containsMutable = false;
|
||||
aSelection.containsPTF = false;
|
||||
aSelection.containsRF = false;
|
||||
var index, item, parent, type, protocol, isContainer, isImmutable, isValid;
|
||||
for (var i=0; i<aSelection.length; ++i) {
|
||||
item = aSelection.item[i];
|
||||
|
@ -1158,8 +1187,10 @@ var BookmarksUtils = {
|
|||
protocol == "find" || protocol == "file";
|
||||
isValid = true;
|
||||
isImmutable = false;
|
||||
if (item == "NC:BookmarksRoot")
|
||||
if (item.Value == "NC:BookmarksRoot") {
|
||||
isImmutable = true;
|
||||
aSelection.containsRF = true;
|
||||
}
|
||||
else if (type != "Bookmark" && type != "BookmarkSeparator" &&
|
||||
type != "Folder" && type != "FolderGroup" &&
|
||||
type != "PersonalToolbarFolder")
|
||||
|
@ -1184,20 +1215,13 @@ var BookmarksUtils = {
|
|||
|
||||
isSelectionValidForInsertion: function (aSelection, aTarget, aAction)
|
||||
{
|
||||
var isValid = new Array(aSelection.length);
|
||||
for (var i=0; i<aSelection.length; ++i)
|
||||
isValid[i] = false;
|
||||
if (!BookmarksUtils.isValidTargetContainer(aTarget.parent, aSelection))
|
||||
if (!BookmarksUtils.isValidTargetContainer(aTarget.parent, aSelection)) {
|
||||
var isValid = new Array(aSelection.length);
|
||||
for (var i=0; i<aSelection.length; ++i)
|
||||
isValid[i] = false;
|
||||
return isValid;
|
||||
for (i=0; i<aSelection.length; ++i) {
|
||||
if (!aSelection.isValid[i])
|
||||
continue;
|
||||
if (!BookmarksUtils.isChildOfContainer(aSelection.item[i], aTarget.parent) ||
|
||||
aAction == "move" && aSelection.parent[i] == aTarget.parent ||
|
||||
aSelection.isContainer[i])
|
||||
isValid[i] = true;
|
||||
}
|
||||
return isValid;
|
||||
return aSelection.isValid;
|
||||
},
|
||||
|
||||
isSelectionValidForDeletion: function (aSelection)
|
||||
|
@ -1236,6 +1260,8 @@ var BookmarksUtils = {
|
|||
{
|
||||
if (!aFolder)
|
||||
return false;
|
||||
if (aFolder.Value == "NC:BookmarksTopRoot")
|
||||
return false;
|
||||
if (aFolder.Value == "NC:BookmarksRoot")
|
||||
return true;
|
||||
|
||||
|
@ -1311,7 +1337,7 @@ var BookmarksUtils = {
|
|||
// kPrefSvc.setBoolPref("browser.bookmarks.import_system_favorites", false);
|
||||
//}
|
||||
|
||||
insertSelection: function (aAction, aSelection, aTarget, aDoCopy)
|
||||
insertSelection: function (aAction, aSelection, aTarget)
|
||||
{
|
||||
var transaction = new BookmarkInsertTransaction(aAction);
|
||||
transaction.item = new Array(aSelection.length);
|
||||
|
@ -1325,15 +1351,9 @@ var BookmarksUtils = {
|
|||
for (var i=0; i<aSelection.length; ++i) {
|
||||
var rSource = aSelection.item[i];
|
||||
|
||||
// disabling cloneFolder for now
|
||||
if (aDoCopy && aSelection.isContainer[i]) {
|
||||
transaction.isValid[i]=false;
|
||||
SOUND.beep();
|
||||
}
|
||||
|
||||
if (transaction.isValid[i]) {
|
||||
if (aDoCopy && aSelection.isContainer[i])
|
||||
rSource = BookmarksUtils.cloneFolder(rSource);
|
||||
if (BMSVC.isBookmarkedResource(rSource))
|
||||
rSource = BMSVC.cloneResource(rSource);
|
||||
transaction.item [i] = rSource;
|
||||
transaction.parent[i] = aTarget.parent;
|
||||
transaction.index [i] = index++;
|
||||
|
@ -1557,6 +1577,30 @@ var BookmarksUtils = {
|
|||
}
|
||||
|
||||
|
||||
function BookmarkTransaction()
|
||||
{
|
||||
}
|
||||
|
||||
BookmarkTransaction.prototype = {
|
||||
BATCH_LIMIT : 8,
|
||||
RDFC : null,
|
||||
BMDS : null,
|
||||
|
||||
beginUpdateBatch: function()
|
||||
{
|
||||
if (this.item.length > this.BATCH_LIMIT) {
|
||||
this.BMDS.beginUpdateBatch();
|
||||
}
|
||||
},
|
||||
|
||||
endUpdateBatch: function()
|
||||
{
|
||||
if (this.item.length > this.BATCH_LIMIT) {
|
||||
this.BMDS.endUpdateBatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function BookmarkInsertTransaction (aAction)
|
||||
{
|
||||
this.wrappedJSObject = this;
|
||||
|
@ -1570,29 +1614,34 @@ function BookmarkInsertTransaction (aAction)
|
|||
|
||||
BookmarkInsertTransaction.prototype =
|
||||
{
|
||||
__proto__: BookmarkTransaction.prototype,
|
||||
|
||||
isTransient: false,
|
||||
RDFC : RDFC,
|
||||
BMDS : BMDS,
|
||||
|
||||
doTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=0; i<this.item.length; ++i) {
|
||||
if (this.isValid[i]) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.InsertElementAt(this.item[i], this.index[i], true);
|
||||
}
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
undoTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
// XXXvarga Can't use |RDFC| here because it's being "reused" elsewhere.
|
||||
var container = Components.classes[kRDFCContractID].createInstance(kRDFCIID);
|
||||
for (var i=this.item.length-1; i>=0; i--) {
|
||||
if (this.isValid[i]) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.RemoveElementAt(this.index[i], true);
|
||||
container.Init(this.BMDS, this.parent[i]);
|
||||
container.RemoveElementAt(this.index[i], true);
|
||||
}
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
redoTransaction: function ()
|
||||
|
@ -1621,29 +1670,32 @@ function BookmarkRemoveTransaction (aAction)
|
|||
|
||||
BookmarkRemoveTransaction.prototype =
|
||||
{
|
||||
__proto__: BookmarkTransaction.prototype,
|
||||
|
||||
isTransient: false,
|
||||
RDFC : RDFC,
|
||||
BMDS : BMDS,
|
||||
|
||||
doTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=0; i<this.item.length; ++i) {
|
||||
if (this.isValid[i]) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.RemoveElementAt(this.index[i], false);
|
||||
}
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
undoTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=this.item.length-1; i>=0; i--) {
|
||||
if (this.isValid[i]) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.InsertElementAt(this.item[i], this.index[i], false);
|
||||
}
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
redoTransaction: function ()
|
||||
|
@ -1671,13 +1723,30 @@ function BookmarkMoveTransaction (aAction, aSelection, aTarget)
|
|||
|
||||
BookmarkMoveTransaction.prototype =
|
||||
{
|
||||
__proto__: BookmarkTransaction.prototype,
|
||||
|
||||
isTransient: false,
|
||||
|
||||
beginUpdateBatch: function()
|
||||
{
|
||||
if (this.selection.length > this.BATCH_LIMIT) {
|
||||
this.BMDS.beginUpdateBatch();
|
||||
}
|
||||
},
|
||||
|
||||
endUpdateBatch: function()
|
||||
{
|
||||
if (this.selection.length > this.BATCH_LIMIT) {
|
||||
this.BMDS.endUpdateBatch();
|
||||
}
|
||||
},
|
||||
|
||||
doTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
BookmarksUtils.removeSelection("move", this.selection);
|
||||
BookmarksUtils.insertSelection("move", this.selection, this.target);
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
undoTransaction : function () {},
|
||||
|
@ -1703,10 +1772,9 @@ function BookmarkImportTransaction (aAction)
|
|||
|
||||
BookmarkImportTransaction.prototype =
|
||||
{
|
||||
__proto__: BookmarkTransaction.prototype,
|
||||
|
||||
isTransient: false,
|
||||
RDFC : RDFC,
|
||||
BMDS : BMDS,
|
||||
|
||||
doTransaction: function ()
|
||||
{
|
||||
|
@ -1714,22 +1782,26 @@ BookmarkImportTransaction.prototype =
|
|||
|
||||
undoTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=this.item.length-1; i>=0; i--) {
|
||||
if (this.isValid[i]) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.RemoveElementAt(this.index[i], true);
|
||||
}
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
redoTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=0; i<this.item.length; ++i) {
|
||||
if (this.isValid[i]) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.InsertElementAt(this.item[i], this.index[i], true);
|
||||
}
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
merge : function (aTransaction) {return false},
|
||||
|
|
|
@ -54,23 +54,21 @@ function Startup()
|
|||
// always open the bookmark top root folder
|
||||
if (!bookmarksView.treeBoxObject.view.isContainerOpen(0))
|
||||
bookmarksView.treeBoxObject.view.toggleOpenState(0);
|
||||
// XXXvarga this should go away once bug 200067 is fixed.
|
||||
if (!bookmarksView.treeBoxObject.view.isContainerEmpty(0))
|
||||
rowIndex = 1;
|
||||
}
|
||||
|
||||
bookmarksView.treeBoxObject.scrollToRow(rowIndex);
|
||||
bookmarksView.treeBoxObject.selection.select(rowIndex);
|
||||
|
||||
windowNode.setAttribute("title", titleString);
|
||||
|
||||
document.getElementById("CommandUpdate_Bookmarks").setAttribute("commandupdater","true");
|
||||
bookmarksView.tree.focus();
|
||||
|
||||
}
|
||||
|
||||
function Shutdown ()
|
||||
function Shutdown()
|
||||
{
|
||||
|
||||
// Store current window position and size in window attributes (for persistence).
|
||||
var win = document.getElementById("bookmark-window");
|
||||
win.setAttribute("x", screenX);
|
||||
|
@ -79,94 +77,6 @@ function Shutdown ()
|
|||
win.setAttribute("width", outerWidth);
|
||||
}
|
||||
|
||||
var gConstructedViewMenuSortItems = false;
|
||||
function fillViewMenu(aEvent)
|
||||
{
|
||||
var adjacentElement = document.getElementById("fill-before-this-node");
|
||||
var popupElement = aEvent.target;
|
||||
|
||||
var bookmarksView = document.getElementById("bookmarks-view");
|
||||
var columns = bookmarksView.columns;
|
||||
|
||||
if (!gConstructedViewMenuSortItems) {
|
||||
for (var i = 0; i < columns.length; ++i) {
|
||||
var accesskey = columns[i].accesskey;
|
||||
var menuitem = document.createElement("menuitem");
|
||||
var name = BookmarksUtils.getLocaleString("SortMenuItem", columns[i].label);
|
||||
menuitem.setAttribute("label", name);
|
||||
menuitem.setAttribute("accesskey", columns[i].accesskey);
|
||||
menuitem.setAttribute("resource", columns[i].resource);
|
||||
menuitem.setAttribute("id", "sortMenuItem:" + columns[i].resource);
|
||||
menuitem.setAttribute("checked", columns[i].sortActive);
|
||||
menuitem.setAttribute("name", "sortSet");
|
||||
menuitem.setAttribute("type", "radio");
|
||||
|
||||
popupElement.insertBefore(menuitem, adjacentElement);
|
||||
}
|
||||
|
||||
gConstructedViewMenuSortItems = true;
|
||||
}
|
||||
|
||||
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
||||
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
||||
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
||||
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
|
||||
|
||||
if (gConstructedViewMenuSortItems) {
|
||||
var resource = bookmarksSortPrefs.getCharPref("resource");
|
||||
var element = document.getElementById("sortMenuItem:" + resource);
|
||||
if (element)
|
||||
element.setAttribute("checked", "true");
|
||||
}
|
||||
|
||||
var sortAscendingMenu = document.getElementById("ascending");
|
||||
var sortDescendingMenu = document.getElementById("descending");
|
||||
var noSortMenu = document.getElementById("natural");
|
||||
|
||||
sortAscendingMenu.setAttribute("checked", "false");
|
||||
sortDescendingMenu.setAttribute("checked", "false");
|
||||
noSortMenu.setAttribute("checked", "false");
|
||||
var direction = bookmarksSortPrefs.getCharPref("direction");
|
||||
if (direction == "natural")
|
||||
sortAscendingMenu.setAttribute("checked", "true");
|
||||
else if (direction == "ascending")
|
||||
sortDescendingMenu.setAttribute("checked", "true");
|
||||
else
|
||||
noSortMenu.setAttribute("checked", "true");
|
||||
}
|
||||
|
||||
function onViewMenuSortItemSelected(aEvent)
|
||||
{
|
||||
var resource = aEvent.target.getAttribute("resource");
|
||||
|
||||
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
||||
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
||||
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
||||
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
|
||||
|
||||
switch (resource) {
|
||||
case "":
|
||||
break;
|
||||
case "direction":
|
||||
var dirn = bookmarksSortPrefs.getCharPref("direction");
|
||||
if (aEvent.target.id == "ascending")
|
||||
bookmarksSortPrefs.setCharPref("direction", "natural");
|
||||
else if (aEvent.target.id == "descending")
|
||||
bookmarksSortPrefs.setCharPref("direction", "ascending");
|
||||
else
|
||||
bookmarksSortPrefs.setCharPref("direction", "descending");
|
||||
break;
|
||||
default:
|
||||
bookmarksSortPrefs.setCharPref("resource", resource);
|
||||
var direction = bookmarksSortPrefs.getCharPref("direction");
|
||||
if (direction == "descending")
|
||||
bookmarksSortPrefs.setCharPref("direction", "natural");
|
||||
break;
|
||||
}
|
||||
|
||||
aEvent.preventCapture();
|
||||
}
|
||||
|
||||
var gConstructedColumnsMenuItems = false;
|
||||
function fillColumnsMenu(aEvent)
|
||||
{
|
||||
|
|
|
@ -113,6 +113,15 @@
|
|||
<key id="bm_key_find"
|
||||
key="&edit.find.keybinding;"
|
||||
command="cmd_bm_find" modifiers="accel"/>
|
||||
|
||||
<key id="bm_key_sortFolder"
|
||||
key="&edit.sortFolder.keybinding;"
|
||||
command="cmd_bm_sortfolder" modifiers="accel"/>
|
||||
|
||||
<key id="bm_key_sortFolderByName"
|
||||
key="&edit.sortFolderByName.keybinding;"
|
||||
command="cmd_bm_sortfolderbyname" modifiers="accel"/>
|
||||
|
||||
<key id="bm_key_properties"
|
||||
key="&edit.properties.keybinding;"
|
||||
command="cmd_bm_properties" modifiers="accel"/>
|
||||
|
@ -140,8 +149,8 @@
|
|||
</menu>
|
||||
<menu id="menu_Edit">
|
||||
<menupopup>
|
||||
<menuitem id="menu_undo" disabled="true"/>
|
||||
<menuitem id="menu_redo" disabled="true"/>
|
||||
<menuitem id="menu_undo"/>
|
||||
<menuitem id="menu_redo"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_bm_cut"
|
||||
label="&cutCmd.label;" accesskey="&cutCmd.accesskey;"
|
||||
|
@ -164,36 +173,35 @@
|
|||
accesskey="&command.moveBookmark.accesskey;"
|
||||
command="cmd_bm_movebookmark"/>
|
||||
<menuseparator/>
|
||||
<menuitem observes="cmd_bm_properties" key="bm_key_properties"
|
||||
label="&command.properties.label;"
|
||||
accesskey="&command.properties.accesskey;" />
|
||||
<menuitem label="&command.sortFolder.label;"
|
||||
accesskey="&command.sortFolder.accesskey;"
|
||||
key="bm_key_sortFolder"
|
||||
command="cmd_bm_sortfolder"/>
|
||||
<menuitem label="&command.sortFolderByName.label;"
|
||||
accesskey="&command.sortFolderByName.accesskey;"
|
||||
key="bm_key_sortFolderByName"
|
||||
command="cmd_bm_sortfolderbyname"/>
|
||||
<menuseparator/>
|
||||
<menuitem label="&command.properties.label;"
|
||||
accesskey="&command.properties.accesskey;"
|
||||
key="bm_key_properties"
|
||||
command="cmd_bm_properties" />
|
||||
</menupopup>
|
||||
</menu>
|
||||
|
||||
<menu id="menu_View">
|
||||
<menupopup onpopupshowing="fillViewMenu(event)"
|
||||
oncommand="onViewMenuSortItemSelected(event);">
|
||||
<menupopup>
|
||||
<menuitem id="viewCommandToolbar" type="checkbox" class="menuitem-iconic"
|
||||
label="&menuitem.view.command.toolbar.label;"
|
||||
accesskey="&menuitem.view.command.toolbar.accesskey;"
|
||||
oncommand="goToggleToolbar('command-toolbar', 'viewCommandToolbar'); event.preventBubble();"
|
||||
persist="checked"/>
|
||||
<menuseparator id="fill-after-this-node"/>
|
||||
<menuitem id="natural" label="&menuitem.view.unsorted.label;"
|
||||
accesskey="&menuitem.view.unsorted.accesskey;"
|
||||
type="radio"
|
||||
resource="direction" name="sortSet"/>
|
||||
<menuseparator id="fill-before-this-node"/>
|
||||
<menuitem id="ascending" label="&menuitem.view.ascending.label;"
|
||||
accesskey="&menuitem.view.ascending.accesskey;"
|
||||
type="radio"
|
||||
resource="direction" name="sortDirectionSet"/>
|
||||
<menuitem id="descending" label="&menuitem.view.descending.label;"
|
||||
accesskey="&menuitem.view.descending.accesskey;"
|
||||
type="radio"
|
||||
resource="direction" name="sortDirectionSet"/>
|
||||
<menuseparator/>
|
||||
<menu id="descending" label="&menuitem.view.show_columns.label;"
|
||||
checked="true"/>
|
||||
<menuitem id="viewCommandSearchbar" type="checkbox" class="menuitem-iconic"
|
||||
label="&menuitem.view.command.searchbar.label;"
|
||||
accesskey="&menuitem.view.command.searchbar.accesskey;"
|
||||
oncommand="goToggleToolbar('bookmarks-search', 'viewCommandSearchbar'); event.preventBubble();"
|
||||
checked="true"/>
|
||||
<menu label="&menuitem.view.show_columns.label;"
|
||||
accesskey="&menuitem.view.show_columns.accesskey;">
|
||||
<menupopup id="columnsPopup" onpopupshowing="fillColumnsMenu(event);"
|
||||
oncommand="onViewMenuColumnItemSelected(event);"/>
|
||||
|
|
|
@ -424,10 +424,8 @@ var BookmarksMenuDNDObserver = {
|
|||
menuTarget.removeChild(menuTarget.lastChild.previousSibling);
|
||||
}
|
||||
|
||||
// disabling ctrl-DND for now bookmarks are not cloned
|
||||
if (aDragSession.dragAction & kCopyAction)
|
||||
SOUND.beep();
|
||||
//BookmarksUtils.insertSelection("drag", selection, selTarget, true);
|
||||
BookmarksUtils.insertSelection("drag", selection, selTarget);
|
||||
else
|
||||
BookmarksUtils.moveSelection("drag", selection, selTarget);
|
||||
|
||||
|
@ -788,8 +786,13 @@ var BookmarksToolbarRDFObserver =
|
|||
},
|
||||
onChange: function (aDataSource, aSource, aProperty, aOldTarget, aNewTarget) {},
|
||||
onMove: function (aDataSource, aOldSource, aNewSource, aProperty, aTarget) {},
|
||||
beginUpdateBatch: function (aDataSource) {},
|
||||
endUpdateBatch: function (aDataSource) {},
|
||||
onBeginUpdateBatch: function (aDataSource) {},
|
||||
onEndUpdateBatch: function (aDataSource) {
|
||||
if (this._overflowTimerInEffect)
|
||||
return;
|
||||
this._overflowTimerInEffect = true;
|
||||
setTimeout(BookmarksToolbar.resizeFunc, 0);
|
||||
},
|
||||
|
||||
_overflowTimerInEffect: false,
|
||||
setOverflowTimeout: function (aSource, aProperty)
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
<command id="cmd_bm_import" oncommand="goDoCommand('cmd_bm_import');"/>
|
||||
<command id="cmd_bm_export" oncommand="goDoCommand('cmd_bm_export');"/>
|
||||
<command id="cmd_bm_movebookmark" oncommand="goDoCommand('cmd_bm_movebookmark');"/>
|
||||
<command id="cmd_bm_sortfolder" oncommand="goDoCommand('cmd_bm_sortfolder');"/>
|
||||
<command id="cmd_bm_sortfolderbyname" oncommand="goDoCommand('cmd_bm_sortfolderbyname');"/>
|
||||
|
||||
<command id="cmd_bm_cut" oncommand="goDoCommand('cmd_bm_cut');"/>
|
||||
<command id="cmd_bm_copy" oncommand="goDoCommand('cmd_bm_copy');"/>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- -*- Mode: HTML; indent-tabs-mode: nil; -*- -->
|
||||
<!--
|
||||
|
@ -51,24 +51,28 @@
|
|||
|
||||
BMSVC.readBookmarks();
|
||||
|
||||
// We implement nsIController
|
||||
// Add controllers and listeners.
|
||||
this.tree.controllers.appendController(this.controller);
|
||||
var olb = document.getAnonymousElementByAttribute(this, "anonid", "bookmarks-tree");
|
||||
olb = olb.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
|
||||
olb.addObserver(this.builderObserver);
|
||||
|
||||
// XXXvarga this observer should go away once bug 120071 is fixed.
|
||||
this.treeBuilder.addObserver(this.builderObserver);
|
||||
|
||||
this.tree.builder.addListener(this.builderListener);
|
||||
|
||||
BMSVC.transactionManager.AddListener(this.transactionListener);
|
||||
|
||||
// Load column settings from persisted attribute
|
||||
var colinfostr = this.getAttribute("colinfo");
|
||||
var colinfo = colinfostr.split(" ");
|
||||
for (var i = 0; i < colinfo.length; ++i) {
|
||||
if (colinfo[i] == "") continue;
|
||||
|
||||
|
||||
var querymarker = colinfo[i].indexOf("?");
|
||||
var anonid = colinfo[i].substring(4, querymarker);
|
||||
var col = document.getAnonymousElementByAttribute(this, "id", anonid);
|
||||
|
||||
|
||||
if (!anonid || !col) break;
|
||||
|
||||
|
||||
var attrstring = colinfo[i].substr(querymarker + 1);
|
||||
|
||||
var attrpairs = attrstring.split("&");
|
||||
|
@ -77,30 +81,19 @@
|
|||
col.setAttribute(pair[0], pair[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Load sort data from preferences
|
||||
this.refreshSort();
|
||||
|
||||
// Observe for changes in sort from other concurrent UI
|
||||
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
||||
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
||||
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
||||
var prefs = prefSvc.getBranch(null);
|
||||
const kPrefBranchInternalIID = Components.interfaces.nsIPrefBranchInternal;
|
||||
var bookmarksPrefsInternal = prefs.QueryInterface(kPrefBranchInternalIID);
|
||||
bookmarksPrefsInternal.addObserver(this.sortChangedObserver.domain,
|
||||
this.sortChangedObserver, false);
|
||||
]]></constructor>
|
||||
<destructor><![CDATA[
|
||||
|
||||
// Remove controllers and listeners.
|
||||
BMSVC.transactionManager.RemoveListener(this.transactionListener);
|
||||
|
||||
this.tree.builder.removeListener(this.builderListener);
|
||||
|
||||
this.treeBuilder.removeObserver(this.builderObserver);
|
||||
|
||||
this.tree.controllers.removeController(this.controller);
|
||||
|
||||
// Save column settings and sort info to persisted attribute
|
||||
var persistString = "";
|
||||
|
||||
var sortResource = NC_NS + "Name";
|
||||
var sortDirection = "none";
|
||||
|
||||
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
|
||||
var child = treecols.firstChild;
|
||||
|
@ -110,33 +103,14 @@
|
|||
formatString = formatString.replace(/%1%/, child.getAttribute("id"));
|
||||
formatString = formatString.replace(/%2%/, child.getAttribute("width"));
|
||||
formatString = formatString.replace(/%3%/, child.getAttribute("hidden"));
|
||||
|
||||
// While we're walking the columns, if we discover the column that represents the
|
||||
// field sorted by, save the resource associated with that column so that we
|
||||
// can save that in prefs (see below)
|
||||
if (child.getAttribute("sortActive") == "true") {
|
||||
sortResource = child.getAttribute("sort");
|
||||
sortDirection = child.getAttribute("sortDirection");
|
||||
}
|
||||
formatString = formatString.replace(/%6%/, child.getAttribute("ordinal"));
|
||||
persistString += formatString;
|
||||
}
|
||||
}
|
||||
child = child.nextSibling;
|
||||
}
|
||||
this.setAttribute("colinfo", persistString);
|
||||
|
||||
document.persist(this.id, "colinfo");
|
||||
|
||||
// Unhook the sort change observer for this tree
|
||||
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
||||
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
||||
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
||||
var prefs = prefSvc.getBranch(null);
|
||||
const kPrefBranchInternalIID = Components.interfaces.nsIPrefBranchInternal;
|
||||
var bookmarksPrefsInternal = prefs.QueryInterface(kPrefBranchInternalIID);
|
||||
bookmarksPrefsInternal.removeObserver(this.sortChangedObserver.domain,
|
||||
this.sortChangedObserver);
|
||||
|
||||
document.persist(this.id, "colinfo");
|
||||
]]></destructor>
|
||||
|
||||
<property name="db">
|
||||
|
@ -145,64 +119,6 @@
|
|||
]]></getter>
|
||||
</property>
|
||||
|
||||
<field name="sortChangedObserver">
|
||||
<![CDATA[
|
||||
({
|
||||
outer: this,
|
||||
domain: "browser.bookmarks.sort",
|
||||
observe: function BMOL_sortChangedObserver(aSubject, aTopic, aPrefName)
|
||||
{
|
||||
if (aTopic != "nsPref:changed") return;
|
||||
if (aPrefName.substr(0, this.domain.length) != this.domain) return;
|
||||
|
||||
this.outer.refreshSort();
|
||||
}
|
||||
})
|
||||
]]>
|
||||
</field>
|
||||
|
||||
<field name="sorted">false</field>
|
||||
<method name="refreshSort">
|
||||
<body>
|
||||
<![CDATA[
|
||||
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
||||
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
||||
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
||||
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
|
||||
|
||||
// This ensures that we don't sort twice in the tree that is clicked on
|
||||
// as a result of 1) the click and 2) the pref listener.
|
||||
if (!this.sorted) {
|
||||
try {
|
||||
var sortResource = bookmarksSortPrefs.getCharPref("resource");
|
||||
var sortDirection = bookmarksSortPrefs.getCharPref("direction");
|
||||
|
||||
// Walk the columns, when we find a column with a sort resource that matches the supplied
|
||||
// data, stop and make sure it's sort active.
|
||||
var treecols = document.getAnonymousElementByAttribute(this, "anonid", "treecols");
|
||||
var child = treecols.firstChild;
|
||||
while (child) {
|
||||
if (child.localName != "splitter") {
|
||||
if (child.getAttribute("sort") == sortResource) {
|
||||
child.setAttribute("sortActive", "true");
|
||||
child.setAttribute("sortDirection", sortDirection);
|
||||
this.treeBuilder.sort(child, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
child = child.nextSibling;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
dump("error in refresh sort:"+e)
|
||||
}
|
||||
}
|
||||
|
||||
this.sorted = false;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="columns">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
|
@ -215,8 +131,6 @@
|
|||
var obj = {
|
||||
label: child.getAttribute("label"),
|
||||
accesskey: child.getAttribute("accesskey"),
|
||||
resource: child.getAttribute("sort"),
|
||||
sortActive: child.getAttribute("sortActive") == "true",
|
||||
hidden: child.getAttribute("hidden")
|
||||
}
|
||||
cols.push(obj);
|
||||
|
@ -377,95 +291,51 @@
|
|||
</method>
|
||||
|
||||
<!--
|
||||
This function saves the current selection state before the tree is rebuilt
|
||||
following a command execution. This allows us to remember which item(s)
|
||||
was/were selected so that the user does not need to constantly refocus the
|
||||
tree to perform a sequence of commands.
|
||||
This function saves the current selection state before the tree is
|
||||
rebuilt.
|
||||
-->
|
||||
<field name="_savedSelection">[]</field>
|
||||
<method name="saveSelection">
|
||||
<body><![CDATA[
|
||||
this._savedSelection = [];
|
||||
var selection = this.treeBoxObject.view.selection;
|
||||
var rangeCount = selection.getRangeCount();
|
||||
var ranges = [];
|
||||
var min = {}; var max = {};
|
||||
for (var i = 0; i < rangeCount; ++i) {
|
||||
selection.getRangeAt(i, min, max);
|
||||
ranges.push({min: min.value, max: max.value});
|
||||
if (selection) {
|
||||
var rangeCount = selection.getRangeCount();
|
||||
var min = {}; var max = {};
|
||||
for (var i = 0; i < rangeCount; ++i) {
|
||||
selection.getRangeAt(i, min, max);
|
||||
for (var j = min.value; j <= max.value; ++j) {
|
||||
var resource = this.treeBuilder.getResourceAtIndex(j);
|
||||
this._savedSelection.push(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._savedSelection = ranges;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
This function restores the selection appropriately after a command executes.
|
||||
This is necessary because most commands trigger a rebuild of the tree which
|
||||
destroys the selection. The restoration of selection is handled in three
|
||||
different ways depending on the type of command that has been executed:
|
||||
1) Commands that remove rows:
|
||||
The row immediately after the first range in the selection is selected,
|
||||
if there is no row immediately after the first range the item before it
|
||||
is selected
|
||||
2) Commands that insert rows:
|
||||
The newly inserted rows are selected
|
||||
3) Commands that do not change the row count
|
||||
The row(s) that was/were operated on remain selected.
|
||||
|
||||
The calls to save/restore are placed in the doCommand method and thus all
|
||||
commands must pass through this gate. The result is that this method becomes
|
||||
the POLICY CENTER FOR POST-VIEW/EDIT SELECTION CHANGES.
|
||||
This function restores the selection appropriately after the tree has
|
||||
been rebuilt.
|
||||
-->
|
||||
<method name="restoreSelection">
|
||||
<parameter name="aCommand"/>
|
||||
<body><![CDATA[
|
||||
var oldRanges = this._savedSelection;
|
||||
var newRanges = [];
|
||||
var selection = this.treeBoxObject.view.selection;
|
||||
if (selection) {
|
||||
selection.selectEventsSuppressed = true;
|
||||
|
||||
switch(aCommand) {
|
||||
// [Category 1] - Commands that remove rows
|
||||
case "cmd_bm_cut":
|
||||
case "cmd_bm_delete":
|
||||
// Since rows have been removed, the row immediately after the first range
|
||||
// in the original selection now has the index of the first item in the first
|
||||
// range.
|
||||
var nextRow = oldRanges[0].min;
|
||||
newRanges.push({min: nextRow, max: nextRow});
|
||||
break;
|
||||
// [Category 2] - Commands that insert rows
|
||||
case "cmd_bm_paste":
|
||||
case "cmd_bm_import":
|
||||
case "cmd_bm_movebookmark":
|
||||
case "cmd_bm_newbookmark":
|
||||
case "cmd_bm_newfolder":
|
||||
case "cmd_bm_newseparator":
|
||||
// [Category 2 bis] - Temporary hack
|
||||
case "cmd_undo":
|
||||
case "cmd_redo":
|
||||
// All items inserted will be selected. The implementation of this model
|
||||
// is left to |preUpdateTreeSelection|, called when an insert transaction is
|
||||
// executed, and |updateTreeSelection| called here.
|
||||
this.updateTreeSelection();
|
||||
break;
|
||||
// [Category 3] - Commands that do not alter the row count
|
||||
case "cmd_bm_copy":
|
||||
case "cmd_bm_properties":
|
||||
case "cmd_bm_rename":
|
||||
case "cmd_bm_setnewbookmarkfolder":
|
||||
case "cmd_bm_setpersonaltoolbarfolder":
|
||||
case "cmd_bm_setnewsearchfolder":
|
||||
case "cmd_bm_export":
|
||||
default:
|
||||
// The selection is unchanged.
|
||||
newRanges = oldRanges;
|
||||
break;
|
||||
selection.clearSelection();
|
||||
for (var i = 0; i < this._savedSelection.length; ++i) {
|
||||
var index = this.treeBuilder.getIndexOfResource(this._savedSelection[i]);
|
||||
if (index >= 0) {
|
||||
selection.toggleSelect(index);
|
||||
}
|
||||
}
|
||||
|
||||
selection.selectEventsSuppressed = false;
|
||||
}
|
||||
|
||||
var newSelection = this.treeBoxObject.view.selection;
|
||||
for (i = 0; i < newRanges.length; ++i)
|
||||
newSelection.rangedSelect(newRanges[i].min, newRanges[i].max, true);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
||||
<field name="_itemToBeToggled"> []</field>
|
||||
<field name="_parentToBeToggled">[]</field>
|
||||
<method name="preUpdateTreeSelection">
|
||||
|
@ -488,7 +358,7 @@
|
|||
this.treeBoxObject.selection.clearSelection();
|
||||
for (var i=0; i<this._itemToBeToggled.length; ++i) {
|
||||
index = this.treeBuilder.getIndexOfResource(this._itemToBeToggled[i]);
|
||||
if (index != -1 && !this.treeBoxObject.selection.isSelected(index))
|
||||
if (index >=0)
|
||||
this.treeBoxObject.selection.toggleSelect(index);
|
||||
}
|
||||
]]></body>
|
||||
|
@ -572,14 +442,44 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="sortBookmarks">
|
||||
<parameter name="aColumn"/>
|
||||
<parameter name="aReverse"/>
|
||||
<body><![CDATA[
|
||||
var confirmed;
|
||||
if (PREF.getBoolPref("browser.bookmarks.confirm_sorting")) {
|
||||
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Components.interfaces.nsIPromptService);
|
||||
var title = BookmarksUtils.getLocaleString("confirm_sorting_title");
|
||||
var message = BookmarksUtils.getLocaleString("confirm_sorting_message");
|
||||
var checkMessage = BookmarksUtils.getLocaleString("confirm_sorting_check_message");
|
||||
var checkValue = {};
|
||||
confirmed = promptService.confirmCheck(window, title, message,
|
||||
checkMessage, checkValue);
|
||||
if (checkValue.value) {
|
||||
PREF.setBoolPref("browser.bookmarks.confirm_sorting", false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
confirmed = true;
|
||||
}
|
||||
if (confirmed) {
|
||||
var folder = RDF.GetResource("NC:BookmarksRoot");
|
||||
var property = BookmarksUtils.getResource(aColumn);
|
||||
var direction =
|
||||
aReverse ? kBMSVCIID.SORT_DESCENDING : kBMSVCIID.SORT_ASCENDING;
|
||||
var foldersFirst = aColumn == "Name";
|
||||
BMDS.sortFolder(folder, property, direction, foldersFirst, true);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- observer -->
|
||||
<field name="DNDObserver" readonly="true"><![CDATA[
|
||||
({
|
||||
mOuter: this,
|
||||
onDragStart: function (aEvent, aXferData, aDragAction)
|
||||
{
|
||||
if (this.mOuter.tree.getAttribute("sortActive") == "true")
|
||||
throw Components.results.NS_OK;
|
||||
var selection = this.mOuter._selection;
|
||||
aXferData.data = BookmarksUtils.getXferDataFromSelection(selection);
|
||||
const kDSIID = Components.interfaces.nsIDragService;
|
||||
|
@ -608,33 +508,46 @@
|
|||
{
|
||||
var selection = this.mOuter._selection;
|
||||
var target = this.mOuter._target;
|
||||
this.mOuter.treeBoxObject.selection.selectEventsSuppressed = true;
|
||||
|
||||
switch (aCommand) {
|
||||
case "cmd_bm_selectAll":
|
||||
this.mOuter.treeBoxObject.selection.selectAll();
|
||||
break;
|
||||
case "cmd_bm_expandfolder":
|
||||
this.mOuter.treeBoxObject.view.toggleOpenState(this.mOuter.currentIndex);
|
||||
break;
|
||||
default:
|
||||
// Notify the datasource that we're about to begin a batch operation
|
||||
var observer = this.mOuter.tree.builder.QueryInterface(Components.interfaces.nsIRDFObserver);
|
||||
observer.beginUpdateBatch(this.db);
|
||||
BookmarksController.doCommand(aCommand, selection, target);
|
||||
observer.endUpdateBatch(this.db);
|
||||
|
||||
this.mOuter.saveSelection();
|
||||
|
||||
var firstVisibleRow = this.mOuter.treeBoxObject.getFirstVisibleRow()
|
||||
this.mOuter.treeBoxObject.selection.currentIndex=-1;
|
||||
this.mOuter.tree.builder.rebuild();
|
||||
// temporary hack: for an unknown reason, rebuilding cause a scroll to the bottom
|
||||
// if the first visible row is not 0
|
||||
this.mOuter.treeBoxObject.scrollToRow(firstVisibleRow);
|
||||
this.mOuter.restoreSelection(aCommand);
|
||||
// Commands that insert rows
|
||||
case "cmd_bm_newfolder":
|
||||
case "cmd_bm_newbookmark":
|
||||
case "cmd_bm_newseparator":
|
||||
case "cmd_bm_import":
|
||||
case "cmd_bm_movebookmark":
|
||||
case "cmd_bm_paste":
|
||||
// XXXvarga undo/redo can insert or remove rows.
|
||||
case "cmd_undo":
|
||||
case "cmd_redo":
|
||||
// All items inserted will be selected. The implementation of
|
||||
// this model is left to |preUpdateTreeSelection|, called when
|
||||
// an insert transaction is executed, and |updateTreeSelection|
|
||||
// called here.
|
||||
BookmarksController.doCommand(aCommand, selection, target);
|
||||
this.mOuter.updateTreeSelection();
|
||||
break;
|
||||
// Commands that remove rows
|
||||
case "cmd_bm_cut":
|
||||
case "cmd_bm_delete":
|
||||
// Since rows have been removed, the row immediately after the
|
||||
// first range in the original selection now has the index of
|
||||
// the first item in the first range.
|
||||
var s = this.mOuter.treeBoxObject.selection;
|
||||
rangeMin = {};
|
||||
rangeMax = {};
|
||||
s.getRangeAt(0, rangeMin, rangeMax);
|
||||
BookmarksController.doCommand(aCommand, selection, target);
|
||||
s.select(rangeMin.value);
|
||||
break;
|
||||
case "cmd_bm_expandfolder":
|
||||
this.mOuter.treeBoxObject.view.toggleOpenState(this.mOuter.currentIndex);
|
||||
break;
|
||||
case "cmd_bm_selectAll":
|
||||
this.mOuter.treeBoxObject.selection.selectAll();
|
||||
break;
|
||||
default:
|
||||
BookmarksController.doCommand(aCommand, selection, target);
|
||||
}
|
||||
this.mOuter.treeBoxObject.selection.selectEventsSuppressed = false;
|
||||
}
|
||||
})
|
||||
]]></field>
|
||||
|
@ -659,10 +572,21 @@
|
|||
mOuter: this,
|
||||
canDropOn: function(index)
|
||||
{
|
||||
return true;
|
||||
var dragSession = DS.getCurrentSession();
|
||||
if (!dragSession)
|
||||
return false;
|
||||
var selection = BookmarksUtils.getSelectionFromXferData(dragSession);
|
||||
return !selection.containsRF;
|
||||
},
|
||||
canDropBeforeAfter: function(index, before)
|
||||
{
|
||||
var dragSession = DS.getCurrentSession();
|
||||
if (!dragSession)
|
||||
return false;
|
||||
var selection = BookmarksUtils.getSelectionFromXferData(dragSession);
|
||||
if (selection.containsRF)
|
||||
return false;
|
||||
|
||||
if (index != 0)
|
||||
return true;
|
||||
if (this.mOuter.getRowResource(index).Value != "NC:BookmarksRoot")
|
||||
|
@ -671,8 +595,7 @@
|
|||
},
|
||||
onDrop: function(row, orientation)
|
||||
{
|
||||
var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService().QueryInterface(Components.interfaces.nsIDragService);
|
||||
var dragSession = dragService.getCurrentSession();
|
||||
var dragSession = DS.getCurrentSession();
|
||||
if (!dragSession)
|
||||
return;
|
||||
var selection = BookmarksUtils.getSelectionFromXferData(dragSession);
|
||||
|
@ -689,10 +612,8 @@
|
|||
}
|
||||
const kDSIID = Components.interfaces.nsIDragService;
|
||||
const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
|
||||
// disabling ctrl-DND for now bookmarks are not cloned
|
||||
if (dragSession.dragAction & kCopyAction)
|
||||
SOUND.beep();
|
||||
//BookmarksUtils.insertSelection("drag", selection, target, true);
|
||||
BookmarksUtils.insertSelection("drag", selection, target);
|
||||
else
|
||||
BookmarksUtils.moveSelection ("drag", selection, target);
|
||||
},
|
||||
|
@ -710,19 +631,7 @@
|
|||
}
|
||||
},
|
||||
|
||||
onCycleHeader: function (aColumnID, aHeaderElement)
|
||||
{
|
||||
const kPrefSvcContractID = "@mozilla.org/preferences;1";
|
||||
const kPrefSvcIID = Components.interfaces.nsIPrefService;
|
||||
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
|
||||
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
|
||||
|
||||
// Sorted! http://www.sorted.org.nz/
|
||||
this.mOuter.sorted = true;
|
||||
|
||||
bookmarksSortPrefs.setCharPref("resource", aHeaderElement.getAttribute("sort"));
|
||||
bookmarksSortPrefs.setCharPref("direction", aHeaderElement.getAttribute("sortDirection"));
|
||||
},
|
||||
onCycleHeader: function (aColumnID, aHeaderElement) {},
|
||||
|
||||
onSelectionChanged: function ()
|
||||
{
|
||||
|
@ -757,8 +666,23 @@
|
|||
})
|
||||
]]></field>
|
||||
|
||||
<!-- nsIXULBuilderListener -->
|
||||
<field name="builderListener"><![CDATA[
|
||||
({
|
||||
mOuter: this,
|
||||
|
||||
willRebuild: function(aBuilder) {
|
||||
this.mOuter.saveSelection();
|
||||
},
|
||||
|
||||
didRebuild: function(aBuilder) {
|
||||
this.mOuter.restoreSelection();
|
||||
}
|
||||
})
|
||||
]]></field>
|
||||
|
||||
<!-- nsITransactionManager listener -->
|
||||
<field name="bookmarkTreeTransactionListener"><![CDATA[
|
||||
<field name="transactionListener"><![CDATA[
|
||||
({
|
||||
|
||||
mOuter: this,
|
||||
|
@ -862,42 +786,43 @@
|
|||
</treechildren>
|
||||
</rule>
|
||||
</template>
|
||||
<treecols anonid="treecols">
|
||||
<treecol id="Name" label="&treecol.name.label;" flex="1" primary="true"
|
||||
class="sortDirectionIndicator"
|
||||
persist="width hidden ordinal"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#Name"
|
||||
sortActive="true" sortDirection="none"/>
|
||||
<treecols anonid="treecols" onclick="if (event.target.localName == 'treecol') this.parentNode.parentNode.parentNode.sortBookmarks(event.target.id, event.ctrlKey || event.metaKey)">
|
||||
<treecol id="Name" flex="1" primary="true"
|
||||
label="&treecol.name.label;"
|
||||
tooltiptext="&treecol.name.tooltip;"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#Name"
|
||||
sortActive="true" sortLocked="true"
|
||||
persist="width hidden ordinal"/>
|
||||
<splitter class="tree-splitter" />
|
||||
<treecol id="URL" label="&treecol.url.label;"
|
||||
flex="1" class="sortDirectionIndicator"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#URL"
|
||||
persist="width hidden ordinal" />
|
||||
<treecol id="URL" flex="1"
|
||||
label="&treecol.url.label;"
|
||||
tooltiptext="&treecol.url.tooltip;"
|
||||
persist="width hidden ordinal"/>
|
||||
<splitter class="tree-splitter" />
|
||||
<treecol id="ShortcutURL" label="&treecol.shortcut.label;"
|
||||
hidden="true" flex="1" class="sortDirectionIndicator"
|
||||
persist="hidden width ordinal"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#ShortcutURL"/>
|
||||
<treecol id="ShortcutURL" flex="1" hidden="true"
|
||||
label="&treecol.shortcut.label;"
|
||||
tooltiptext="&treecol.shortcut.tooltip;"
|
||||
persist="hidden width ordinal"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="Description" label="&treecol.description.label;"
|
||||
flex="1" class="sortDirectionIndicator"
|
||||
persist="hidden width ordinal"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#Description"/>
|
||||
<treecol id="Description" flex="1"
|
||||
label="&treecol.description.label;"
|
||||
tooltiptext="&treecol.description.tooltip;"
|
||||
persist="hidden width ordinal"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="AddDate" label="&treecol.addedon.label;"
|
||||
hidden="true" flex="1" class="sortDirectionIndicator"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#BookmarkAddDate"
|
||||
persist="width hidden ordinal" />
|
||||
<treecol id="BookmarkAddDate" flex="1" hidden="true"
|
||||
label="&treecol.addedon.label;"
|
||||
tooltiptext="&treecol.addedon.tooltip;"
|
||||
persist="width hidden ordinal"/>
|
||||
<splitter class="tree-splitter" />
|
||||
<treecol id="LastModDate" label="&treecol.lastmod.label;"
|
||||
hidden="true" flex="1" class="sortDirectionIndicator"
|
||||
sort="rdf:http://home.netscape.com/WEB-rdf#LastModifiedDate"
|
||||
persist="width hidden ordinal" />
|
||||
<treecol id="LastModifiedDate" flex="1" hidden="true"
|
||||
label="&treecol.lastmod.label;"
|
||||
tooltiptext="&treecol.lastmod.tooltip;"
|
||||
persist="width hidden ordinal"/>
|
||||
<splitter class="tree-splitter" />
|
||||
<treecol id="LastVisitDate" label="&treecol.lastvisit.label;"
|
||||
hidden="true" flex="1" class="sortDirectionIndicator"
|
||||
sort="rdf:http://home.netscape.com/WEB-rdf#LastVisitDate"
|
||||
persist="width hidden ordinal" />
|
||||
<treecol id="LastVisitDate" flex="1" hidden="true"
|
||||
label="&treecol.lastvisit.label;"
|
||||
tooltiptext="&treecol.lastvisit.tooltip;"
|
||||
persist="width hidden ordinal"/>
|
||||
</treecols>
|
||||
</tree>
|
||||
<statusbar class="chromeclass-status" xbl:inherits="hidden=hidestatusbar" hidden="false">
|
||||
|
@ -906,13 +831,6 @@
|
|||
</vbox>
|
||||
</xbl:content>
|
||||
<implementation>
|
||||
<constructor>
|
||||
// Adding the transaction listener
|
||||
BMSVC.transactionManager.AddListener(this.bookmarkTreeTransactionListener);
|
||||
</constructor>
|
||||
<destructor>
|
||||
BMSVC.transactionManager.RemoveListener(this.bookmarkTreeTransactionListener);
|
||||
</destructor>
|
||||
<field name="clickCount">2</field>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
@ -963,7 +881,7 @@
|
|||
<treecols anonid="treecols">
|
||||
<treecol id="Name" flex="1" primary="true" hideheader="true"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#Name"
|
||||
sortActive="true" sortDirection="none"/>
|
||||
sortActive="true" sortLocked="true"/>
|
||||
</treecols>
|
||||
</tree>
|
||||
</xbl:content>
|
||||
|
@ -993,7 +911,7 @@
|
|||
<treecols anonid="treecols">
|
||||
<treecol id="Name" flex="1" primary="true" hideheader="true"
|
||||
sort="rdf:http://home.netscape.com/NC-rdf#Name"
|
||||
sortActive="true" sortDirection="none"/>
|
||||
sortActive="true" sortLocked="true"/>
|
||||
</treecols>
|
||||
</tree>
|
||||
</xbl:content>
|
||||
|
|
|
@ -33,11 +33,14 @@ comm.jar:
|
|||
content/communicator/bookmarks/bm-panel.js
|
||||
content/communicator/bookmarks/findBookmark.xul
|
||||
content/communicator/bookmarks/findBookmark.js
|
||||
content/communicator/bookmarks/sortFolder.xul
|
||||
content/communicator/bookmarks/sortFolder.js
|
||||
|
||||
en-US.jar:
|
||||
locale/en-US/communicator/bookmarks/addBookmark.dtd (locale/en-US/addBookmark.dtd)
|
||||
locale/en-US/communicator/bookmarks/bm-props.dtd (locale/en-US/bm-props.dtd)
|
||||
locale/en-US/communicator/bookmarks/bookmarks.dtd (locale/en-US/bookmarks.dtd)
|
||||
locale/en-US/communicator/bookmarks/bookmarks.properties (locale/en-US/bookmarks.properties)
|
||||
locale/en-US/communicator/bookmarks/bookmarks.properties (locale/en-US/bookmarks.properties)
|
||||
locale/en-US/communicator/bookmarks/bookmarksOverlay.dtd (locale/en-US/bookmarksOverlay.dtd)
|
||||
locale/en-US/communicator/bookmarks/findBookmark.dtd (locale/en-US/findBookmark.dtd)
|
||||
locale/en-US/communicator/bookmarks/sortFolder.dtd (locale/en-US/sortFolder.dtd)
|
||||
|
|
|
@ -57,17 +57,19 @@
|
|||
<!ENTITY command.moveBookmark.accesskey "M">
|
||||
<!ENTITY command.addBookmark.label "Add...">
|
||||
<!ENTITY command.manageBookmarks.label "Manage">
|
||||
<!ENTITY command.sortFolder.label "Sort Folder...">
|
||||
<!ENTITY command.sortFolder.accesskey "S">
|
||||
<!ENTITY edit.sortFolder.keybinding "S">
|
||||
<!ENTITY command.sortFolderByName.label "Sort Folder by Name">
|
||||
<!ENTITY command.sortFolderByName.accesskey "N">
|
||||
<!ENTITY edit.sortFolderByName.keybinding "N">
|
||||
|
||||
<!ENTITY menuitem.view.command.toolbar.label "Toolbar">
|
||||
<!ENTITY menuitem.view.command.toolbar.accesskey "t">
|
||||
<!ENTITY menuitem.view.unsorted.label "Unsorted">
|
||||
<!ENTITY menuitem.view.unsorted.accesskey "u">
|
||||
<!ENTITY menuitem.view.ascending.label "A > Z Sort Order">
|
||||
<!ENTITY menuitem.view.ascending.accesskey "a">
|
||||
<!ENTITY menuitem.view.descending.label "Z > A Sort Order">
|
||||
<!ENTITY menuitem.view.descending.accesskey "z">
|
||||
<!ENTITY menuitem.view.command.searchbar.label "Search bar">
|
||||
<!ENTITY menuitem.view.command.searchbar.accesskey "S">
|
||||
<!ENTITY menuitem.view.show_columns.label "Show columns">
|
||||
<!ENTITY menuitem.view.show_columns.accesskey "S">
|
||||
<!ENTITY menuitem.view.show_columns.accesskey "c">
|
||||
<!ENTITY menuitem.newbookmarkfolder.label "Set as New Bookmark Folder">
|
||||
<!ENTITY menuitem.newbookmarkfolder.accesskey "b">
|
||||
<!ENTITY menuitem.newinternetsearchfolder.label "Set as New Internet Search Folder">
|
||||
|
@ -77,18 +79,25 @@
|
|||
|
||||
<!ENTITY treecol.name.label "Name">
|
||||
<!ENTITY treecol.name.accesskey "n">
|
||||
<!ENTITY treecol.name.tooltip "Click to sort by name">
|
||||
<!ENTITY treecol.url.label "Location">
|
||||
<!ENTITY treecol.url.accesskey "l">
|
||||
<!ENTITY treecol.url.tooltip "Click to sort by location">
|
||||
<!ENTITY treecol.shortcut.label "Keyword">
|
||||
<!ENTITY treecol.shortcut.accesskey "k">
|
||||
<!ENTITY treecol.addedon.label "Added">
|
||||
<!ENTITY treecol.addedon.accesskey "a">
|
||||
<!ENTITY treecol.lastmod.label "Last Modified">
|
||||
<!ENTITY treecol.lastmod.accesskey "m">
|
||||
<!ENTITY treecol.lastvisit.label "Last Visited">
|
||||
<!ENTITY treecol.lastvisit.accesskey "b">
|
||||
<!ENTITY treecol.shortcut.tooltip "Click to sort by keyword">
|
||||
<!ENTITY treecol.description.label "Description">
|
||||
<!ENTITY treecol.description.accesskey "d">
|
||||
<!ENTITY treecol.description.tooltip "Click to sort by description">
|
||||
<!ENTITY treecol.addedon.label "Added">
|
||||
<!ENTITY treecol.addedon.accesskey "a">
|
||||
<!ENTITY treecol.addedon.tooltip "Click to sort by added">
|
||||
<!ENTITY treecol.lastmod.label "Last Modified">
|
||||
<!ENTITY treecol.lastmod.accesskey "m">
|
||||
<!ENTITY treecol.lastmod.tooltip "Click to sort by last modified">
|
||||
<!ENTITY treecol.lastvisit.label "Last Visited">
|
||||
<!ENTITY treecol.lastvisit.accesskey "b">
|
||||
<!ENTITY treecol.lastvisit.tooltip "Click to sort by last visit">
|
||||
|
||||
<!ENTITY bookmarksWindowTitle.label "Bookmark Manager">
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ cmd_bm_selectAll = Select All
|
|||
cmd_bm_rename = Rename...
|
||||
cmd_bm_renamebookmark2 = Change Location...
|
||||
cmd_bm_properties = Properties
|
||||
cmd_bm_sortfolderbyname = Sort Folder by Name
|
||||
cmd_bm_sortfolder = Sort Folder...
|
||||
|
||||
cmd_bm_openinnewwindow = Open in New Window
|
||||
cmd_bm_openinnewtab = Open in New Tab
|
||||
|
@ -90,3 +92,6 @@ EnterExport = Export bookmark file:
|
|||
|
||||
search_button_label = Find
|
||||
|
||||
confirm_sorting_title = Confirm
|
||||
confirm_sorting_message = If you sort this list, you will not be able to Undo it. Are you sure you want to sort the list?
|
||||
confirm_sorting_check_message = Don't ask me this again
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!ENTITY window.title "Sort Folder">
|
||||
|
||||
<!ENTITY sortOptions.label "Sort options">
|
||||
<!ENTITY description.label "&brandShortName; can sort individual folders. Use these options to customize the sorting for this Folder.">
|
||||
|
||||
<!ENTITY sortBy.label "Sort by:">
|
||||
<!ENTITY sortBy.name.label "Name">
|
||||
<!ENTITY sortBy.url.label "Location">
|
||||
<!ENTITY sortBy.shortcutUrl.label "Keyword">
|
||||
<!ENTITY sortBy.description.label "Description">
|
||||
<!ENTITY sortBy.bookmarkAddDate.label "Added">
|
||||
<!ENTITY sortBy.lastModifiedDate.label "Last Modified">
|
||||
<!ENTITY sortBy.lastVisitDate.label "Last Visited">
|
||||
|
||||
<!ENTITY sortOrder.label "Sort order:">
|
||||
<!ENTITY sortOrder.ascending.label "A > Z">
|
||||
<!ENTITY sortOrder.descending.label "Z > A">
|
||||
|
||||
<!ENTITY sortFoldersFirst.label "Sort folders first">
|
||||
<!ENTITY sortRecursively.label "Sort recursively">
|
|
@ -0,0 +1,51 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jan Varga <varga@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function onAccept() {
|
||||
var sortOptions = window.arguments[0];
|
||||
sortOptions.accepted = true;
|
||||
sortOptions.sortBy = document.getElementById("sortBy").value;
|
||||
sortOptions.sortOrder = document.getElementById("sortOrder").value;
|
||||
sortOptions.sortFoldersFirst = document.getElementById("sortFoldersFirst").checked;
|
||||
sortOptions.sortRecursively = document.getElementById("sortRecursively").checked;
|
||||
}
|
||||
|
||||
function onSortByChanged() {
|
||||
var sortBy = document.getElementById("sortBy");
|
||||
var sortFoldersFirst = document.getElementById("sortFoldersFirst");
|
||||
sortFoldersFirst.checked = sortBy.value == "Name";
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is mozilla.org code.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Netscape Communications Corp.
|
||||
- Portions created by the Initial Developer are Copyright (C) 2003
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Jan Varga <varga@netscape.com>
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<!DOCTYPE dialog [
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" >
|
||||
%brandDTD;
|
||||
<!ENTITY % sortFolderDTD SYSTEM "chrome://communicator/locale/bookmarks/sortFolder.dtd">
|
||||
%sortFolderDTD;
|
||||
]>
|
||||
|
||||
<dialog id="sortFolder"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="&window.title;"
|
||||
style="width: 30em;"
|
||||
buttons="accept,cancel"
|
||||
ondialogaccept="return onAccept();">
|
||||
|
||||
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/sortFolder.js"/>
|
||||
|
||||
<tabbox>
|
||||
<tabs>
|
||||
<tab label="&sortOptions.label;"/>
|
||||
</tabs>
|
||||
<tabpanels>
|
||||
<vbox>
|
||||
<separator class="thin"/>
|
||||
<hbox align="start">
|
||||
<image class="message-icon"/>
|
||||
<separator class="thin" orient="vertical"/>
|
||||
<description flex="1">
|
||||
&description.label;
|
||||
</description>
|
||||
</hbox>
|
||||
<separator class="thin"/>
|
||||
<grid>
|
||||
<columns>
|
||||
<column/>
|
||||
<column flex="1"/>
|
||||
</columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&sortBy.label;"/>
|
||||
<menulist id="sortBy" oncommand="onSortByChanged()">
|
||||
<menupopup>
|
||||
<menuitem value="Name" label="&sortBy.name.label;"/>
|
||||
<menuitem value="URL" label="&sortBy.url.label;"/>
|
||||
<menuitem value="ShortcutURL" label="&sortBy.shortcutUrl.label;"/>
|
||||
<menuitem value="Description" label="&sortBy.description.label;"/>
|
||||
<menuitem value="BookmarkAddDate" label="&sortBy.bookmarkAddDate.label;"/>
|
||||
<menuitem value="LastModifiedDate" label="&sortBy.lastModifiedDate.label;"/>
|
||||
<menuitem value="LastVisitDate" label="&sortBy.lastVisitDate.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&sortOrder.label;"/>
|
||||
<menulist id="sortOrder">
|
||||
<menupopup>
|
||||
<menuitem value="ascending" label="&sortOrder.ascending.label;"/>
|
||||
<menuitem value="descending" label="&sortOrder.descending.label;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<separator class="thin"/>
|
||||
<checkbox id="sortFoldersFirst" label="&sortFoldersFirst.label;"
|
||||
checked="true"/>
|
||||
<checkbox id="sortRecursively" label="&sortRecursively.label;"/>
|
||||
<separator class="thin"/>
|
||||
</vbox>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
|
||||
</dialog>
|
|
@ -45,6 +45,7 @@ REQUIRES = xpcom \
|
|||
windowwatcher \
|
||||
unicharutil \
|
||||
txmgr \
|
||||
locale \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsBookmarksService.cpp
|
||||
|
|
|
@ -85,6 +85,14 @@
|
|||
#include "nsIPlatformCharset.h"
|
||||
#include "nsIPref.h"
|
||||
|
||||
// for sorting
|
||||
#include "nsCollationCID.h"
|
||||
#include "nsILocaleService.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include <SHLOBJ.H>
|
||||
#include <INTSHCUT.H>
|
||||
|
@ -123,6 +131,8 @@ nsIRDFResource *kWEB_LastPingModDate;
|
|||
nsIRDFResource *kWEB_LastCharset;
|
||||
nsIRDFResource *kWEB_LastPingContentLen;
|
||||
nsIRDFLiteral *kTrueLiteral;
|
||||
nsIRDFLiteral *kEmptyLiteral;
|
||||
nsIRDFDate *kEmptyDate;
|
||||
nsIRDFResource *kNC_Parent;
|
||||
nsIRDFResource *kNC_BookmarkCommand_NewBookmark;
|
||||
nsIRDFResource *kNC_BookmarkCommand_NewFolder;
|
||||
|
@ -153,6 +163,7 @@ static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
|||
static NS_DEFINE_CID(kPlatformCharsetCID, NS_PLATFORMCHARSET_CID);
|
||||
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
|
||||
static NS_DEFINE_CID(kCharsetAliasCID, NS_CHARSETALIAS_CID);
|
||||
static NS_DEFINE_CID(kCollationFactoryCID, NS_COLLATIONFACTORY_CID);
|
||||
|
||||
#define URINC_BOOKMARKS_TOPROOT_STRING "NC:BookmarksTopRoot"
|
||||
#define URINC_BOOKMARKS_ROOT_STRING "NC:BookmarksRoot"
|
||||
|
@ -174,6 +185,7 @@ PRInt32 gRefCnt=0;
|
|||
nsIRDFService *gRDF;
|
||||
nsIRDFContainerUtils *gRDFC;
|
||||
nsICharsetAlias *gCharsetAlias;
|
||||
nsICollation *gCollation;
|
||||
PRBool gLoadedBookmarks = PR_FALSE;
|
||||
PRBool gImportedSystemBookmarks = PR_FALSE;
|
||||
|
||||
|
@ -204,6 +216,18 @@ bm_AddRefGlobals()
|
|||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get charset alias service");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsILocaleService> ls = do_GetService(NS_LOCALESERVICE_CONTRACTID);
|
||||
if (ls) {
|
||||
nsCOMPtr<nsILocale> locale;
|
||||
ls->GetApplicationLocale(getter_AddRefs(locale));
|
||||
if (locale) {
|
||||
nsCOMPtr<nsICollationFactory> factory = do_CreateInstance(kCollationFactoryCID);
|
||||
if (factory) {
|
||||
factory->CreateCollation(locale, &gCollation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gRDF->GetResource(NS_LITERAL_CSTRING(kURINC_BookmarksTopRoot),
|
||||
&kNC_BookmarksTopRoot);
|
||||
gRDF->GetResource(NS_LITERAL_CSTRING(kURINC_BookmarksRoot),
|
||||
|
@ -276,6 +300,10 @@ bm_AddRefGlobals()
|
|||
|
||||
gRDF->GetLiteral(NS_LITERAL_STRING("true").get(), &kTrueLiteral);
|
||||
|
||||
gRDF->GetLiteral(NS_LITERAL_STRING("").get(), &kEmptyLiteral);
|
||||
|
||||
gRDF->GetDateLiteral(0, &kEmptyDate);
|
||||
|
||||
gRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "command?cmd=newbookmark"),
|
||||
&kNC_BookmarkCommand_NewBookmark);
|
||||
gRDF->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "command?cmd=newfolder"),
|
||||
|
@ -327,6 +355,8 @@ bm_ReleaseGlobals()
|
|||
gCharsetAlias = nsnull;
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(gCollation);
|
||||
|
||||
NS_IF_RELEASE(kNC_Bookmark);
|
||||
NS_IF_RELEASE(kNC_BookmarkSeparator);
|
||||
NS_IF_RELEASE(kNC_BookmarkAddDate);
|
||||
|
@ -353,6 +383,8 @@ bm_ReleaseGlobals()
|
|||
NS_IF_RELEASE(kWEB_LastVisitDate);
|
||||
NS_IF_RELEASE(kNC_Parent);
|
||||
NS_IF_RELEASE(kTrueLiteral);
|
||||
NS_IF_RELEASE(kEmptyLiteral);
|
||||
NS_IF_RELEASE(kEmptyDate);
|
||||
NS_IF_RELEASE(kWEB_Schedule);
|
||||
NS_IF_RELEASE(kWEB_ScheduleActive);
|
||||
NS_IF_RELEASE(kWEB_Status);
|
||||
|
@ -1574,6 +1606,71 @@ BookmarkParser::setFolderHint(nsIRDFResource *newSource, nsIRDFResource *objType
|
|||
}
|
||||
|
||||
|
||||
class SortInfo {
|
||||
public:
|
||||
SortInfo(PRInt32 aDirection, PRBool aFoldersFirst)
|
||||
: mDirection(aDirection),
|
||||
mFoldersFirst(aFoldersFirst) {
|
||||
}
|
||||
|
||||
protected:
|
||||
PRInt32 mDirection;
|
||||
PRBool mFoldersFirst;
|
||||
|
||||
friend class nsBookmarksService;
|
||||
};
|
||||
|
||||
class ElementInfo {
|
||||
public:
|
||||
ElementInfo(nsIRDFResource* aElement, nsIRDFNode* aNode, PRBool aIsFolder)
|
||||
: mElement(aElement), mNode(aNode), mIsFolder(aIsFolder) {
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIRDFResource> mElement;
|
||||
nsCOMPtr<nsIRDFNode> mNode;
|
||||
PRBool mIsFolder;
|
||||
|
||||
friend class nsBookmarksService;
|
||||
};
|
||||
|
||||
// Note, that elements are deleted only when the array goes away.
|
||||
// Any call on this array that would result in an element being removed or
|
||||
// replaced should make sure that the element gets deleted.
|
||||
class ElementArray : public nsAutoVoidArray
|
||||
{
|
||||
public:
|
||||
virtual ~ElementArray();
|
||||
|
||||
ElementInfo* ElementAt(PRInt32 aIndex) const {
|
||||
return NS_STATIC_CAST(ElementInfo*, nsAutoVoidArray::ElementAt(aIndex));
|
||||
}
|
||||
|
||||
ElementInfo* operator[](PRInt32 aIndex) const {
|
||||
return ElementAt(aIndex);
|
||||
}
|
||||
|
||||
void Clear();
|
||||
};
|
||||
|
||||
ElementArray::~ElementArray()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ElementArray::Clear()
|
||||
{
|
||||
PRInt32 index = Count();
|
||||
while (--index >= 0)
|
||||
{
|
||||
ElementInfo* elementInfo = ElementAt(index);
|
||||
delete elementInfo;
|
||||
}
|
||||
nsAutoVoidArray::Clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsBookmarksService implementation
|
||||
|
||||
|
@ -2513,10 +2610,11 @@ nsBookmarksService::Release()
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMPL_QUERY_INTERFACE8(nsBookmarksService,
|
||||
NS_IMPL_QUERY_INTERFACE9(nsBookmarksService,
|
||||
nsIBookmarksService,
|
||||
nsIRDFDataSource,
|
||||
nsIRDFRemoteDataSource,
|
||||
nsIRDFPropagatableDataSource,
|
||||
nsIRDFObserver,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
|
@ -2637,6 +2735,245 @@ nsBookmarksService::CreateGroupInContainer(const PRUnichar* aName,
|
|||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
nsBookmarksService::Compare(const void* aElement1, const void* aElement2, void* aData)
|
||||
{
|
||||
const ElementInfo* elementInfo1 =
|
||||
NS_STATIC_CAST(ElementInfo*, NS_CONST_CAST(void*, aElement1));
|
||||
const ElementInfo* elementInfo2 =
|
||||
NS_STATIC_CAST(ElementInfo*, NS_CONST_CAST(void*, aElement2));
|
||||
SortInfo* sortInfo = (SortInfo*)aData;
|
||||
|
||||
if (sortInfo->mFoldersFirst) {
|
||||
if (elementInfo1->mIsFolder) {
|
||||
if (!elementInfo2->mIsFolder) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (elementInfo2->mIsFolder) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 result = 0;
|
||||
|
||||
nsIRDFNode* node1 = elementInfo1->mNode;
|
||||
nsIRDFNode* node2 = elementInfo2->mNode;
|
||||
|
||||
// Literals?
|
||||
nsCOMPtr<nsIRDFLiteral> literal1 = do_QueryInterface(node1);
|
||||
if (literal1) {
|
||||
nsCOMPtr<nsIRDFLiteral> literal2 = do_QueryInterface(node2);
|
||||
if (literal2) {
|
||||
const PRUnichar* value1;
|
||||
literal1->GetValueConst(&value1);
|
||||
const PRUnichar* value2;
|
||||
literal2->GetValueConst(&value2);
|
||||
|
||||
if (gCollation) {
|
||||
gCollation->CompareString(kCollationCaseInSensitive,
|
||||
nsDependentString(value1),
|
||||
nsDependentString(value2),
|
||||
&result);
|
||||
}
|
||||
else {
|
||||
result = ::Compare(nsDependentString(value1),
|
||||
nsDependentString(value2),
|
||||
nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
|
||||
return result * sortInfo->mDirection;
|
||||
}
|
||||
}
|
||||
|
||||
// Dates?
|
||||
nsCOMPtr<nsIRDFDate> date1 = do_QueryInterface(node1);
|
||||
if (date1) {
|
||||
nsCOMPtr<nsIRDFDate> date2 = do_QueryInterface(node2);
|
||||
if (date2) {
|
||||
PRTime value1;
|
||||
date1->GetValue(&value1);
|
||||
PRTime value2;
|
||||
date2->GetValue(&value2);
|
||||
|
||||
PRInt64 delta;
|
||||
LL_SUB(delta, value1, value2);
|
||||
|
||||
if (LL_IS_ZERO(delta))
|
||||
result = 0;
|
||||
else if (LL_GE_ZERO(delta))
|
||||
result = 1;
|
||||
else
|
||||
result = -1;
|
||||
|
||||
return result * sortInfo->mDirection;
|
||||
}
|
||||
}
|
||||
|
||||
// Ack! Apples & oranges.
|
||||
return 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBookmarksService::Sort(nsIRDFResource* aFolder, nsIRDFResource* aProperty,
|
||||
PRInt32 aDirection, PRBool aFoldersFirst,
|
||||
PRBool aRecurse)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIRDFContainer> container =
|
||||
do_CreateInstance("@mozilla.org/rdf/container;1", &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = container->Init(mInner, aFolder);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> elements;
|
||||
rv = container->GetElements(getter_AddRefs(elements));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
ElementArray elementArray;
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(rv = elements->HasMoreElements(&hasMore)) &&
|
||||
hasMore) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
rv = elements->GetNext(getter_AddRefs(supports));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> element = do_QueryInterface(supports, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> node;
|
||||
rv = mInner->GetTarget(element, aProperty, PR_TRUE, getter_AddRefs(node));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (!node) {
|
||||
if (aProperty == kNC_BookmarkAddDate ||
|
||||
aProperty == kWEB_LastModifiedDate ||
|
||||
aProperty == kWEB_LastVisitDate) {
|
||||
node = do_QueryInterface(kEmptyDate);
|
||||
}
|
||||
else {
|
||||
node = do_QueryInterface(kEmptyLiteral);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool isContainer;
|
||||
rv = gRDFC->IsContainer(mInner, element, &isContainer);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRBool isGroup;
|
||||
rv = mInner->HasAssertion(element, kNC_FolderGroup, kTrueLiteral,
|
||||
PR_TRUE, &isGroup);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
ElementInfo* elementInfo = new ElementInfo(element, node,
|
||||
isContainer && !isGroup);
|
||||
if (!elementInfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
elementArray.AppendElement(elementInfo);
|
||||
|
||||
if (isContainer && aRecurse) {
|
||||
rv = Sort(element, aProperty, aDirection, aFoldersFirst, aRecurse);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
SortInfo sortInfo(aDirection, aFoldersFirst);
|
||||
elementArray.Sort(Compare, &sortInfo);
|
||||
|
||||
// XXXvarga If we ever make it so that ordinals are guaranteed to be unique,
|
||||
// the code below can be significantly simplified.
|
||||
for (PRInt32 j = elementArray.Count() - 1; j >= 0; --j) {
|
||||
ElementInfo* elementInfo = elementArray[j];
|
||||
|
||||
PRInt32 oldIndex;
|
||||
rv = gRDFC->IndexOf(mInner, aFolder, elementInfo->mElement, &oldIndex);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// The old index is 1 based.
|
||||
if (oldIndex != j + 1) {
|
||||
nsCOMPtr<nsIRDFResource> oldOrdinal;
|
||||
rv = gRDFC->IndexToOrdinalResource(oldIndex, getter_AddRefs(oldOrdinal));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> newOrdinal;
|
||||
rv = gRDFC->IndexToOrdinalResource(j + 1, getter_AddRefs(newOrdinal));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// We need to find the correct element for the old ordinal,
|
||||
// it happens that there are two elements with the same ordinal.
|
||||
nsCOMPtr<nsISimpleEnumerator> elements;
|
||||
rv = mInner->GetTargets(aFolder, oldOrdinal, PR_TRUE,
|
||||
getter_AddRefs(elements));
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(rv = elements->HasMoreElements(&hasMore)) &&
|
||||
hasMore) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
rv = elements->GetNext(getter_AddRefs(supports));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> element = do_QueryInterface(supports);
|
||||
if (element == elementInfo->mElement) {
|
||||
rv = mInner->Unassert(aFolder, oldOrdinal, element);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
rv = mInner->Assert(aFolder, newOrdinal, element, PR_TRUE);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::SortFolder(nsIRDFResource* aFolder,
|
||||
nsIRDFResource* aProperty,
|
||||
PRInt32 aDirection,
|
||||
PRBool aFoldersFirst,
|
||||
PRBool aRecurse)
|
||||
{
|
||||
#ifdef DEBUG_varga
|
||||
PRIntervalTime startTime = PR_IntervalNow();
|
||||
#endif
|
||||
|
||||
BeginUpdateBatch();
|
||||
SetPropagateChanges(PR_FALSE);
|
||||
nsresult rv = Sort(aFolder, aProperty, aDirection, aFoldersFirst,
|
||||
aRecurse);
|
||||
SetPropagateChanges(PR_TRUE);
|
||||
EndUpdateBatch();
|
||||
|
||||
#ifdef DEBUG_varga
|
||||
PRIntervalTime endTime = PR_IntervalNow();
|
||||
printf("Time spent in SortFolder(): %d msec\n", PR_IntervalToMilliseconds(endTime - startTime));
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::CreateBookmark(const PRUnichar* aName,
|
||||
const char* aURL,
|
||||
|
@ -2774,6 +3111,63 @@ nsBookmarksService::CreateSeparator(nsIRDFResource** aResult)
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::CloneResource(nsIRDFResource* aSource,
|
||||
nsIRDFResource** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> newResource;
|
||||
nsresult rv = gRDF->GetAnonymousResource(getter_AddRefs(newResource));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> arcs;
|
||||
rv = mInner->ArcLabelsOut(aSource, getter_AddRefs(arcs));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(arcs->HasMoreElements(&hasMore)) && hasMore) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
rv = arcs->GetNext(getter_AddRefs(supports));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRDFResource> property = do_QueryInterface(supports, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Don't duplicate the folder type.
|
||||
// (NC:PersonalToolbarFolder, NC:NewBookmarkFolder, etc...)
|
||||
PRBool isFolderType;
|
||||
rv = property->EqualsNode(kNC_FolderType, &isFolderType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isFolderType)
|
||||
continue;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> target;
|
||||
rv = mInner->GetTarget(aSource, property, PR_TRUE, getter_AddRefs(target));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Test if the arc points to a child.
|
||||
PRBool isOrdinal;
|
||||
rv = gRDFC->IsOrdinalProperty(property, &isOrdinal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (isOrdinal) {
|
||||
nsCOMPtr<nsIRDFResource> oldChild = do_QueryInterface(target);
|
||||
nsCOMPtr<nsIRDFResource> newChild;
|
||||
rv = CloneResource(oldChild, getter_AddRefs(newChild));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mInner->Assert(newResource, property, newChild, PR_TRUE);
|
||||
}
|
||||
else {
|
||||
rv = mInner->Assert(newResource, property, target, PR_TRUE);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
NS_ADDREF(*aResult = newResource);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::AddBookmarkImmediately(const char *aURI,
|
||||
const PRUnichar *aTitle,
|
||||
|
@ -2803,8 +3197,8 @@ nsBookmarksService::AddBookmarkImmediately(const char *aURI,
|
|||
getter_AddRefs(bookmark));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBookmarksService::IsBookmarkedInternal(nsIRDFResource *bookmark, PRBool *isBookmarkedFlag)
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::IsBookmarkedResource(nsIRDFResource *bookmark, PRBool *isBookmarkedFlag)
|
||||
{
|
||||
if (!bookmark) return NS_ERROR_UNEXPECTED;
|
||||
if (!isBookmarkedFlag) return NS_ERROR_UNEXPECTED;
|
||||
|
@ -2868,7 +3262,7 @@ nsBookmarksService::IsBookmarked(const char* aURL, PRBool* aIsBookmarked)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return IsBookmarkedInternal(bookmark, aIsBookmarked);
|
||||
return IsBookmarkedResource(bookmark, aIsBookmarked);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3123,7 +3517,7 @@ nsBookmarksService::GetSynthesizedType(nsIRDFResource *aNode, nsIRDFNode **aType
|
|||
{
|
||||
*aType = kNC_Folder;
|
||||
}
|
||||
else if (NS_SUCCEEDED(rv = IsBookmarkedInternal(aNode,
|
||||
else if (NS_SUCCEEDED(rv = IsBookmarkedResource(aNode,
|
||||
&isBookmarkedFlag)) && (isBookmarkedFlag == PR_TRUE))
|
||||
{
|
||||
*aType = kNC_Bookmark;
|
||||
|
@ -3367,9 +3761,9 @@ nsBookmarksService::ImportSystemBookmarks(nsIRDFResource* aParentFolder)
|
|||
|
||||
BookmarkParser parser;
|
||||
parser.Init(ieFavoritesFile, mInner);
|
||||
BeginUpdateBatch(this);
|
||||
BeginUpdateBatch();
|
||||
parser.Parse(aParentFolder, kNC_Bookmark);
|
||||
EndUpdateBatch(this);
|
||||
EndUpdateBatch();
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
|
@ -4167,16 +4561,10 @@ nsBookmarksService::getFolderViaHint(nsIRDFResource *objType, PRBool fallbackFla
|
|||
|
||||
if ((rv != NS_RDF_NO_VALUE) && (oldSource))
|
||||
{
|
||||
const char *uri = nsnull;
|
||||
oldSource->GetValueConst(&uri);
|
||||
if (uri)
|
||||
{
|
||||
PRBool isBookmarkedFlag = PR_FALSE;
|
||||
if (NS_SUCCEEDED(rv = IsBookmarked(uri, &isBookmarkedFlag)) &&
|
||||
(isBookmarkedFlag == PR_TRUE))
|
||||
{
|
||||
*folder = oldSource;
|
||||
}
|
||||
PRBool isBookmarkedFlag = PR_FALSE;
|
||||
if (NS_SUCCEEDED(rv = IsBookmarkedResource(oldSource, &isBookmarkedFlag)) &&
|
||||
isBookmarkedFlag) {
|
||||
*folder = oldSource;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4422,6 +4810,24 @@ nsBookmarksService::FlushTo(const char *aURI)
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFPropagatableDataSource
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::GetPropagateChanges(PRBool* aPropagateChanges)
|
||||
{
|
||||
nsCOMPtr<nsIRDFPropagatableDataSource> propagatable = do_QueryInterface(mInner);
|
||||
return propagatable->GetPropagateChanges(aPropagateChanges);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::SetPropagateChanges(PRBool aPropagateChanges)
|
||||
{
|
||||
nsCOMPtr<nsIRDFPropagatableDataSource> propagatable = do_QueryInterface(mInner);
|
||||
return propagatable->SetPropagateChanges(aPropagateChanges);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation methods
|
||||
|
||||
|
@ -4496,9 +4902,9 @@ nsBookmarksService::ReadFavorites()
|
|||
{
|
||||
BookmarkParser parser;
|
||||
parser.Init(ieFavoritesFile, mInner);
|
||||
BeginUpdateBatch(this);
|
||||
BeginUpdateBatch();
|
||||
parser.Parse(kNC_IEFavoritesRoot, kNC_IEFavorite);
|
||||
EndUpdateBatch(this);
|
||||
EndUpdateBatch();
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> ieTitleLiteral;
|
||||
rv = gRDF->GetLiteral(ieTitle.get(), getter_AddRefs(ieTitleLiteral));
|
||||
|
@ -4673,9 +5079,9 @@ nsBookmarksService::LoadBookmarks()
|
|||
parser.ParserFoundIEFavoritesRoot(&foundIERoot);
|
||||
}
|
||||
|
||||
BeginUpdateBatch(this);
|
||||
BeginUpdateBatch();
|
||||
parser.Parse(kNC_BookmarksRoot, kNC_Bookmark);
|
||||
EndUpdateBatch(this);
|
||||
EndUpdateBatch();
|
||||
mBookmarksAvailable = PR_TRUE;
|
||||
|
||||
PRBool foundPTFolder = PR_FALSE;
|
||||
|
@ -5411,7 +5817,7 @@ nsBookmarksService::CanAccept(nsIRDFResource* aSource,
|
|||
nsresult rv;
|
||||
PRBool isBookmarkedFlag = PR_FALSE, canAcceptFlag = PR_FALSE, isOrdinal;
|
||||
|
||||
if (NS_SUCCEEDED(rv = IsBookmarkedInternal(aSource, &isBookmarkedFlag)) &&
|
||||
if (NS_SUCCEEDED(rv = IsBookmarkedResource(aSource, &isBookmarkedFlag)) &&
|
||||
(isBookmarkedFlag == PR_TRUE) &&
|
||||
(NS_SUCCEEDED(rv = gRDFC->IsOrdinalProperty(aProperty, &isOrdinal))))
|
||||
{
|
||||
|
@ -5450,7 +5856,6 @@ nsBookmarksService::OnAssert(nsIRDFDataSource* aDataSource,
|
|||
{
|
||||
if (mUpdateBatchNest != 0) return NS_OK;
|
||||
|
||||
|
||||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i)
|
||||
{
|
||||
|
@ -5514,13 +5919,13 @@ nsBookmarksService::OnMove(nsIRDFDataSource* aDataSource,
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsBookmarksService::OnBeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
if (mUpdateBatchNest++ == 0)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
(void) mObservers[i]->BeginUpdateBatch(aDataSource);
|
||||
(void) mObservers[i]->OnBeginUpdateBatch(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5528,18 +5933,15 @@ nsBookmarksService::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
nsBookmarksService::OnEndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
if (mUpdateBatchNest > 0)
|
||||
{
|
||||
--mUpdateBatchNest;
|
||||
}
|
||||
NS_ASSERTION(mUpdateBatchNest > 0, "badly nested update batch");
|
||||
|
||||
if (mUpdateBatchNest == 0)
|
||||
if (--mUpdateBatchNest == 0)
|
||||
{
|
||||
PRInt32 count = mObservers.Count();
|
||||
for (PRInt32 i = 0; i < count; ++i) {
|
||||
(void) mObservers[i]->EndUpdateBatch(aDataSource);
|
||||
(void) mObservers[i]->OnEndUpdateBatch(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFRemoteDataSource.h"
|
||||
#include "nsIRDFPropagatableDataSource.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsISupportsArray.h"
|
||||
|
@ -69,6 +70,7 @@ class nsIOutputStream;
|
|||
class nsBookmarksService : public nsIBookmarksService,
|
||||
public nsIRDFDataSource,
|
||||
public nsIRDFRemoteDataSource,
|
||||
public nsIRDFPropagatableDataSource,
|
||||
public nsIStreamListener,
|
||||
public nsIRDFObserver,
|
||||
public nsIObserver,
|
||||
|
@ -172,14 +174,18 @@ protected:
|
|||
void AnnotateBookmarkSchedule(nsIRDFResource* aSource,
|
||||
PRBool scheduleFlag);
|
||||
|
||||
nsresult IsBookmarkedInternal(nsIRDFResource *bookmark,
|
||||
PRBool *isBookmarkedFlag);
|
||||
|
||||
nsresult InsertResource(nsIRDFResource* aResource,
|
||||
nsIRDFResource* aParentFolder, PRInt32 aIndex);
|
||||
|
||||
nsresult getLocaleString(const char *key, nsString &str);
|
||||
|
||||
static int PR_CALLBACK
|
||||
Compare(const void* aElement1, const void* aElement2, void* aData);
|
||||
|
||||
nsresult
|
||||
Sort(nsIRDFResource* aFolder, nsIRDFResource* aProperty,
|
||||
PRInt32 aDirection, PRBool aFoldersFirst, PRBool aRecurse);
|
||||
|
||||
nsresult LoadBookmarks();
|
||||
nsresult initDatasource();
|
||||
|
||||
|
@ -289,9 +295,20 @@ public:
|
|||
nsIRDFResource* aCommand,
|
||||
nsISupportsArray/*<nsIRDFResource>*/* aArguments);
|
||||
|
||||
NS_IMETHOD BeginUpdateBatch() {
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHOD EndUpdateBatch() {
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
||||
// nsIRDFRemoteDataSource
|
||||
NS_DECL_NSIRDFREMOTEDATASOURCE
|
||||
|
||||
// nsIRDFPropagatableDataSource
|
||||
NS_DECL_NSIRDFPROPAGATABLEDATASOURCE
|
||||
|
||||
// nsIRDFObserver
|
||||
NS_DECL_NSIRDFOBSERVER
|
||||
};
|
||||
|
|
|
@ -97,8 +97,8 @@ var RDF_observer =
|
|||
|
||||
onChange: function(ds, src, prop, old_target, new_target) { },
|
||||
onMove: function(ds, old_src, new_src, prop, target) { },
|
||||
beginUpdateBatch: function(ds) { },
|
||||
endUpdateBatch: function(ds) { }
|
||||
onBeginUpdateBatch: function(ds) { },
|
||||
onEndUpdateBatch: function(ds) { }
|
||||
};
|
||||
|
||||
function
|
||||
|
|
|
@ -1315,6 +1315,18 @@ nsHTTPIndex::DoCommand(nsISupportsArray *aSources, nsIRDFResource *aCommand,
|
|||
return(rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPIndex::BeginUpdateBatch()
|
||||
{
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPIndex::EndUpdateBatch()
|
||||
{
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPIndex::GetAllCmds(nsIRDFResource *aSource, nsISimpleEnumerator **_retval)
|
||||
{
|
||||
|
|
|
@ -262,23 +262,17 @@ var downloadViewController = {
|
|||
selectedItems = getSelectedItems();
|
||||
// Figure out where to place the selection after deletion
|
||||
var newSelectionPos = gDownloadView.contentView.getIndexOfItem(selectedItems[0]);
|
||||
|
||||
gDownloadManager.startBatchUpdate();
|
||||
|
||||
// Notify the datasource that we're about to begin a batch operation
|
||||
var observer = gDownloadView.builder.QueryInterface(Components.interfaces.nsIRDFObserver);
|
||||
var ds = gDownloadView.database;
|
||||
observer.beginUpdateBatch(ds);
|
||||
|
||||
var ds = window.arguments[0];
|
||||
ds.beginUpdateBatch();
|
||||
for (i = 0; i <= selectedItems.length - 1; ++i) {
|
||||
gDownloadManager.removeDownload(selectedItems[i].id);
|
||||
}
|
||||
ds.endUpdateBatch();
|
||||
|
||||
gDownloadManager.endBatchUpdate();
|
||||
observer.endUpdateBatch(ds);
|
||||
var remote = window.arguments[0].QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
|
||||
remote.Flush();
|
||||
gDownloadView.builder.rebuild();
|
||||
// If there's nothing on the panel now, skip setting the selection
|
||||
if (gDownloadView.treeBoxObject.view && gDownloadView.treeBoxObject.view.rowCount > 0) {
|
||||
// Select the item that replaced the first deleted one
|
||||
|
|
|
@ -678,8 +678,12 @@ nsDownloadManager::StartBatchUpdate()
|
|||
NS_IMETHODIMP
|
||||
nsDownloadManager::EndBatchUpdate()
|
||||
{
|
||||
--mBatches;
|
||||
return NS_OK;
|
||||
nsresult rv = NS_OK;
|
||||
if (--mBatches == 0) {
|
||||
nsCOMPtr<nsIRDFRemoteDataSource> remote = do_QueryInterface(mDataSource);
|
||||
rv = remote->Flush();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -63,21 +63,6 @@ interface nsIBrowserHistory : nsISupports
|
|||
*/
|
||||
void removePage(in string aURL);
|
||||
|
||||
/**
|
||||
* startBatchUpdate
|
||||
* Signals the beginning of some kind of batch update (e.g. delete).
|
||||
* Observers won't be notified until there are no batches in progress
|
||||
* (a startBatchUpdate call should always be followed by one to
|
||||
* endBatchUpdate).
|
||||
*/
|
||||
void startBatchUpdate();
|
||||
|
||||
/**
|
||||
* endBatchUpdate
|
||||
* Signals the end of a batch update.
|
||||
*/
|
||||
void endBatchUpdate();
|
||||
|
||||
/**
|
||||
* removePagesFromHost
|
||||
* Remove all pages from the given host.
|
||||
|
|
|
@ -223,14 +223,12 @@ nsHistoryController.prototype =
|
|||
if (!gGlobalHistory)
|
||||
gGlobalHistory = Components.classes["@mozilla.org/browser/global-history;1"].getService(Components.interfaces.nsIBrowserHistory);
|
||||
gGlobalHistory.removePagesFromHost(gLastHostname, false)
|
||||
gHistoryTree.builder.rebuild();
|
||||
return true;
|
||||
|
||||
case "cmd_deleteByDomain":
|
||||
if (!gGlobalHistory)
|
||||
gGlobalHistory = Components.classes["@mozilla.org/browser/global-history;1"].getService(Components.interfaces.nsIBrowserHistory);
|
||||
gGlobalHistory.removePagesFromHost(gLastDomain, true)
|
||||
gHistoryTree.builder.rebuild();
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
|
|
@ -1102,7 +1102,7 @@ nsGlobalHistory::RemoveMatchingRows(rowMatchCallback aMatchFunc,
|
|||
err = mTable->GetCount(mEnv, &count);
|
||||
if (err != 0) return NS_ERROR_FAILURE;
|
||||
|
||||
StartBatchUpdate();
|
||||
BeginUpdateBatch();
|
||||
|
||||
// Begin the batch.
|
||||
int marker;
|
||||
|
@ -1162,7 +1162,7 @@ nsGlobalHistory::RemoveMatchingRows(rowMatchCallback aMatchFunc,
|
|||
err = mTable->EndBatchChangeHint(mEnv, &marker);
|
||||
NS_ASSERTION(err == 0, "error ending batch");
|
||||
|
||||
EndBatchUpdate();
|
||||
EndUpdateBatch();
|
||||
|
||||
return ( err == 0) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2171,6 +2171,65 @@ nsGlobalHistory::GetAllResources(nsISimpleEnumerator** aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::BeginUpdateBatch()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
++mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->OnBeginUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::EndUpdateBatch()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
--mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->OnEndUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2212,66 +2271,6 @@ nsGlobalHistory::FlushTo(const char *aURI)
|
|||
return(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::StartBatchUpdate()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
++mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->BeginUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGlobalHistory::EndBatchUpdate()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
--mBatchesInProgress;
|
||||
|
||||
// we could call mObservers->EnumerateForwards() here
|
||||
// to save the addref/release on each observer, but
|
||||
// it's unlikely that anyone but the tree builder
|
||||
// is observing us
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = 0; i < PRInt32(count); ++i) {
|
||||
nsIRDFObserver* observer = NS_STATIC_CAST(nsIRDFObserver*, mObservers->ElementAt(i));
|
||||
|
||||
NS_ASSERTION(observer != nsnull, "null ptr");
|
||||
if (! observer)
|
||||
continue;
|
||||
|
||||
rv = observer->EndUpdateBatch(this);
|
||||
NS_RELEASE(observer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsGlobalHistory
|
||||
|
|
|
@ -1993,3 +1993,12 @@ NS_IMETHODIMP nsCharsetMenu::DoCommand(nsISupportsArray* aSources,
|
|||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCharsetMenu::BeginUpdateBatch()
|
||||
{
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCharsetMenu::EndUpdateBatch()
|
||||
{
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
|
|
@ -974,3 +974,19 @@ RelatedLinksHandlerImpl::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSource
|
|||
{
|
||||
return mInner->DoCommand(aSources, aCommand, aArguments);
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RelatedLinksHandlerImpl::BeginUpdateBatch()
|
||||
{
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RelatedLinksHandlerImpl::EndUpdateBatch()
|
||||
{
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
|
|
@ -110,11 +110,11 @@ var RDF_observer =
|
|||
{
|
||||
},
|
||||
|
||||
beginUpdateBatch : function(ds)
|
||||
onBeginUpdateBatch : function(ds)
|
||||
{
|
||||
},
|
||||
|
||||
endUpdateBatch : function(ds)
|
||||
onEndUpdateBatch : function(ds)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2343,6 +2343,18 @@ InternetSearchDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSourc
|
|||
return(NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InternetSearchDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return mInner->BeginUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InternetSearchDataSource::EndUpdateBatch()
|
||||
{
|
||||
return mInner->EndUpdateBatch();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InternetSearchDataSource::AddSearchEngine(const char *engineURL, const char *iconURL,
|
||||
const PRUnichar *suggestedTitle, const PRUnichar *suggestedCategory)
|
||||
|
|
|
@ -986,3 +986,19 @@ LocalSearchDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
|||
{
|
||||
return(NS_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
LocalSearchDataSource::BeginUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
LocalSearchDataSource::EndUpdateBatch()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -144,11 +144,11 @@ var panels_observer = {
|
|||
onMove : function(ds,old_src,new_src,prop,target) {
|
||||
//debug ("observer: move");
|
||||
},
|
||||
beginUpdateBatch : function(ds) {
|
||||
//debug ("observer: beginUpdateBatch");
|
||||
onBeginUpdateBatch : function(ds) {
|
||||
//debug ("observer: onBeginUpdateBatch");
|
||||
},
|
||||
endUpdateBatch : function(ds) {
|
||||
//debug ("observer: endUpdateBatch");
|
||||
onEndUpdateBatch : function(ds) {
|
||||
//debug ("observer: onEndUpdateBatch");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -691,11 +691,11 @@ var panel_observer = {
|
|||
onMove : function(ds,old_src,new_src,prop,target) {
|
||||
//debug ("observer: move");
|
||||
},
|
||||
beginUpdateBatch : function(ds) {
|
||||
//debug ("observer: beginUpdateBatch");
|
||||
onBeginUpdateBatch : function(ds) {
|
||||
//debug ("observer: onBeginUpdateBatch");
|
||||
},
|
||||
endUpdateBatch : function(ds) {
|
||||
//debug ("observer: endUpdateBatch");
|
||||
onEndUpdateBatch : function(ds) {
|
||||
//debug ("observer: onEndUpdateBatch");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -575,3 +575,18 @@ NS_IMETHODIMP nsWindowDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResou
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void beginUpdateBatch (); */
|
||||
NS_IMETHODIMP nsWindowDataSource::BeginUpdateBatch()
|
||||
{
|
||||
if (mInner)
|
||||
return mInner->BeginUpdateBatch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void endUpdateBatch (); */
|
||||
NS_IMETHODIMP nsWindowDataSource::EndUpdateBatch()
|
||||
{
|
||||
if (mInner)
|
||||
return mInner->EndUpdateBatch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -149,16 +149,18 @@ function nsTreeController_delete()
|
|||
return false;
|
||||
|
||||
var datasource = this.tree.database;
|
||||
var dsEnum = datasource.GetDataSources();
|
||||
var dsEnum = datasource.GetDataSources();
|
||||
dsEnum.getNext();
|
||||
var ds = dsEnum.getNext();
|
||||
var ds = dsEnum.getNext()
|
||||
.QueryInterface(Components.interfaces.nsIRDFDataSource);
|
||||
|
||||
var count = this.treeSelection.count;
|
||||
|
||||
// XXX 9 is a random number, just looking for a sweetspot
|
||||
// don't want to rebuild tree content for just a few items
|
||||
if (count > 9)
|
||||
ds.QueryInterface(Components.interfaces.nsIBrowserHistory).startBatchUpdate();
|
||||
if (count > 9) {
|
||||
ds.beginUpdateBatch();
|
||||
}
|
||||
|
||||
var min = new Object();
|
||||
var max = new Object();
|
||||
|
@ -186,17 +188,16 @@ function nsTreeController_delete()
|
|||
|
||||
// otherwise remove the parent/child assertion then
|
||||
var containment = gRDF.GetResource("http://home.netscape.com/NC-rdf#child");
|
||||
ds.QueryInterface(Components.interfaces.nsIRDFDataSource).Unassert(parentIDRes, containment, IDRes);
|
||||
ds.Unassert(parentIDRes, containment, IDRes);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
if (count > 9) {
|
||||
ds.QueryInterface(Components.interfaces.nsIBrowserHistory).endBatchUpdate();
|
||||
this.tree.builder.rebuild();
|
||||
}
|
||||
if (count > 9) {
|
||||
ds.endUpdateBatch();
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
try {
|
||||
var remote = datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
|
||||
remote.Flush();
|
||||
|
|
Загрузка…
Ссылка в новой задаче