mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 00:32:11 +00:00
Bug 168411 Move bookmarks transactions into a JS service (adding a bookmark leaks the Add Bookmark dialog) r=sspitzer, sr+a=mconnor
This commit is contained in:
parent
0db7c90051
commit
dca4d1ab35
@ -21,6 +21,7 @@
|
||||
#
|
||||
# Contributor(s):
|
||||
# Ben Goodger <ben@netscape.com> (Original Author)
|
||||
# Joey Minta <jminta@gmail.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
|
||||
@ -42,6 +43,8 @@ const ADD_BM_DIALOG_FEATURES = "centerscreen,chrome,dialog,resizable,modal";
|
||||
const ADD_BM_DIALOG_FEATURES = "centerscreen,chrome,dialog,resizable,dependent";
|
||||
#endif
|
||||
|
||||
const kBATCH_LIMIT = 4;
|
||||
|
||||
var gNC_NS, gWEB_NS, gRDF_NS, gXUL_NS, gNC_NS_CMD;
|
||||
|
||||
// definition of the services frequently used for bookmarks
|
||||
@ -84,6 +87,7 @@ var kIOIID;
|
||||
var IOSVC;
|
||||
|
||||
var gBmProperties;
|
||||
var gBkmkTxnSvc;
|
||||
|
||||
// should be moved in a separate file
|
||||
function initServices()
|
||||
@ -135,6 +139,8 @@ function initServices()
|
||||
RDF.GetResource(gNC_NS+"Description"),
|
||||
RDF.GetResource(gNC_NS+"WebPanel"),
|
||||
RDF.GetResource(gNC_NS+"FeedURL")];
|
||||
gBkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
|
||||
.getService(Components.interfaces.nsIBookmarkTransactionManager);
|
||||
}
|
||||
|
||||
function initBMService()
|
||||
@ -142,8 +148,6 @@ function initBMService()
|
||||
kBMSVCIID = Components.interfaces.nsIBookmarksService;
|
||||
BMDS = RDF.GetDataSource("rdf:bookmarks");
|
||||
BMSVC = BMDS.QueryInterface(kBMSVCIID);
|
||||
BookmarkTransaction.prototype.RDFC = RDFC;
|
||||
BookmarkTransaction.prototype.BMDS = BMDS;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -415,14 +419,14 @@ var BookmarksCommand = {
|
||||
|
||||
undoBookmarkTransaction: function ()
|
||||
{
|
||||
BMSVC.transactionManager.undoTransaction();
|
||||
gBkmkTxnSvc.undo();
|
||||
BookmarksUtils.refreshSearch();
|
||||
BookmarksUtils.flushDataSource();
|
||||
},
|
||||
|
||||
redoBookmarkTransaction: function ()
|
||||
{
|
||||
BMSVC.transactionManager.redoTransaction();
|
||||
gBkmkTxnSvc.redo();
|
||||
BookmarksUtils.refreshSearch();
|
||||
BookmarksUtils.flushDataSource();
|
||||
},
|
||||
@ -456,7 +460,7 @@ var BookmarksCommand = {
|
||||
sBookmarkItem += aSelection.item[i].Value + "\n";
|
||||
|
||||
// save the selection property into text string that we will use later in paste function
|
||||
// and in BookmarkInsertTransaction
|
||||
// and in INSERT tranasactions
|
||||
// (if the selection is folder or livemark save all childs property)
|
||||
var aType = BookmarksUtils.resolveType(aSelection.item[i]);
|
||||
if (aType == "Livemark") {
|
||||
@ -900,15 +904,17 @@ var BookmarksCommand = {
|
||||
this.doBookmarksCommand(rTarget, gNC_NS_CMD+"import", args);
|
||||
var countAfter = parseInt(BookmarksUtils.getProperty(rTarget, gRDF_NS+"nextVal"));
|
||||
|
||||
var transaction = new BookmarkImportTransaction("import");
|
||||
if (countAfter - countBefore > 1)
|
||||
gBkmkTxnSvc.startBatch();
|
||||
for (var index = countBefore; index < countAfter; index++) {
|
||||
var nChildArc = RDFCU.IndexToOrdinalResource(index);
|
||||
var rChild = BMDS.GetTarget(rTarget, nChildArc, true);
|
||||
transaction.item .push(rChild);
|
||||
transaction.parent .push(rTarget);
|
||||
transaction.index .push(index);
|
||||
gBkmkTxnSvc.createAndCommitTxn(gBkmkTxnSvc.IMPORT, "IMPORT", rChild, index,
|
||||
rTarget, 0, null);
|
||||
}
|
||||
BMSVC.transactionManager.doTransaction(transaction);
|
||||
if (countAfter - countBefore > 1)
|
||||
gBkmkTxnSvc.endBatch();
|
||||
|
||||
BookmarksUtils.flushDataSource();
|
||||
},
|
||||
|
||||
@ -1111,10 +1117,10 @@ var BookmarksController = {
|
||||
switch(aCommand) {
|
||||
case "cmd_undo":
|
||||
case "cmd_bm_undo":
|
||||
return BMSVC.transactionManager.numberOfUndoItems > 0;
|
||||
return gBkmkTxnSvc.canUndo();
|
||||
case "cmd_redo":
|
||||
case "cmd_bm_redo":
|
||||
return BMSVC.transactionManager.numberOfRedoItems > 0;
|
||||
return gBkmkTxnSvc.canRedo();
|
||||
case "cmd_paste":
|
||||
if (ptype0 == "Livemark" || (aTarget && !BookmarksUtils.isValidTargetContainer(aTarget.parent)))
|
||||
return false;
|
||||
@ -1548,11 +1554,11 @@ var BookmarksUtils = {
|
||||
|
||||
removeSelection: function (aAction, aSelection)
|
||||
{
|
||||
var transaction = new BookmarkRemoveTransaction(aAction);
|
||||
transaction.item = [];
|
||||
transaction.parent = [];
|
||||
transaction.index = [];
|
||||
transaction.removedProp = [];
|
||||
if (aSelection.length > 1)
|
||||
gBkmkTxnSvc.startBatch();
|
||||
if (aSelection.length > this.BATCH_LIMIT && aAction != "move")
|
||||
BMDS.beginUpdateBatch();
|
||||
|
||||
for (var i = 0; i < aSelection.length; ++i) {
|
||||
// try to put back aSelection.parent[i] if it's null, so we can delete after searching
|
||||
if (aSelection.parent[i] == null)
|
||||
@ -1560,32 +1566,37 @@ var BookmarksUtils = {
|
||||
|
||||
if (aSelection.parent[i]) {
|
||||
RDFC.Init(BMDS, aSelection.parent[i]);
|
||||
transaction.item .push(aSelection.item[i]);
|
||||
transaction.parent.push(aSelection.parent[i]);
|
||||
transaction.index .push(RDFC.IndexOf(aSelection.item[i]));
|
||||
|
||||
// save the selection property into array that uses later in BookmarkRemoveTransaction
|
||||
// save the selection property into array that is used later in
|
||||
// when performing the REMOVE transaction
|
||||
// (if the selection is folder save all childs property)
|
||||
var propArray;
|
||||
if (aAction != "move") {
|
||||
var propArray = [];
|
||||
propArray.push([aSelection.item[i], null, null, null, null, null, null]);
|
||||
propArray = [aSelection.item[i], null, null, null, null, null, null];
|
||||
var aType = BookmarksUtils.resolveType(aSelection.item[i]);
|
||||
if (aType != "Livemark") {// don't change livemark properties
|
||||
for (var j = 0; j < gBmProperties.length; ++j) {
|
||||
var oldValue = BMDS.GetTarget(aSelection.item[i], gBmProperties[j], true);
|
||||
if (oldValue)
|
||||
propArray[0][j+1] = oldValue.QueryInterface(kRDFLITIID);
|
||||
propArray[j+1] = oldValue.QueryInterface(kRDFLITIID);
|
||||
}
|
||||
}
|
||||
if (aType == "Folder" || aType == "Livemark")
|
||||
BookmarksUtils.getAllChildren(aSelection.item[i], propArray);
|
||||
transaction.removedProp.push(propArray);
|
||||
} else {
|
||||
transaction.removedProp.push(null);
|
||||
}
|
||||
|
||||
var proplength = propArray ? propArray.length : 0;
|
||||
gBkmkTxnSvc.createAndCommitTxn(gBkmkTxnSvc.REMOVE, aAction,
|
||||
aSelection.item[i],
|
||||
RDFC.IndexOf(aSelection.item[i]),
|
||||
aSelection.parent[i],
|
||||
proplength, propArray);
|
||||
}
|
||||
}
|
||||
BMSVC.transactionManager.doTransaction(transaction);
|
||||
if (aSelection.length > 1)
|
||||
gBkmkTxnSvc.endBatch();
|
||||
if (aSelection.length > this.BATCH_LIMIT && aAction != "move")
|
||||
BMDS.beginUpdateBatch();
|
||||
return true;
|
||||
},
|
||||
|
||||
@ -1645,20 +1656,22 @@ var BookmarksUtils = {
|
||||
|
||||
insertSelection: function (aAction, aSelection, aTarget, aTargetIndex)
|
||||
{
|
||||
var transaction = new BookmarkInsertTransaction(aAction);
|
||||
transaction.item = new Array(aSelection.length);
|
||||
transaction.parent = new Array(aSelection.length);
|
||||
transaction.index = new Array(aSelection.length);
|
||||
transaction.removedProp = new Array(aSelection.length);
|
||||
var item, removedProps;
|
||||
var index = aTarget.index;
|
||||
var brokenIndex = aTarget.index;
|
||||
|
||||
if (aSelection.length > 1)
|
||||
gBkmkTxnSvc.startBatch();
|
||||
if (aSelection.length > this.BATCH_LIMIT && aAction != "move")
|
||||
BMDS.beginUpdateBatch();
|
||||
|
||||
for (var i=0; i<aSelection.length; ++i) {
|
||||
var rSource = aSelection.item[i];
|
||||
if (BMSVC.isBookmarkedResource(rSource))
|
||||
rSource = BMSVC.cloneResource(rSource);
|
||||
transaction.item [i] = rSource;
|
||||
transaction.parent[i] = aTarget.parent;
|
||||
item = rSource;
|
||||
// we only have aSelection.prop if insertSelection call by paste action we don't use it for move
|
||||
transaction.removedProp[i] = aSelection.prop ? aSelection.prop[i] : null;
|
||||
removedProps = aSelection.prop ? aSelection.prop[i] : null;
|
||||
// Broken Insert Code attempts to always insert items in the
|
||||
// right place (i.e. after the selected item). However, because
|
||||
// of RDF Container suckyness, this code gets very confused, due
|
||||
@ -1667,19 +1680,25 @@ var BookmarksUtils = {
|
||||
// The -1 is there to handle inserting into the persontal toolbar
|
||||
// folder via right-click on the PTF.
|
||||
if (aTarget.index == -1) {
|
||||
transaction.index[i] = -1;
|
||||
index = -1;
|
||||
} else {
|
||||
#ifdef BROKEN_INSERT_CODE
|
||||
if (aTargetIndex == -1)
|
||||
transaction.index [i] = (++index);
|
||||
index = (++brokenIndex);
|
||||
else
|
||||
transaction.index [i] = (index++);
|
||||
index = (brokenIndex++);
|
||||
#else
|
||||
transaction.index [i] = index++;
|
||||
index = brokenIndex++;
|
||||
#endif
|
||||
}
|
||||
var proplength = removedProps ? removedProps.length : 0;
|
||||
gBkmkTxnSvc.createAndCommitTxn(gBkmkTxnSvc.INSERT, aAction, item, index,
|
||||
aTarget.parent, proplength, removedProps);
|
||||
}
|
||||
BMSVC.transactionManager.doTransaction(transaction);
|
||||
if (aSelection.length > 1)
|
||||
gBkmkTxnSvc.endBatch();
|
||||
if (aSelection.length > this.BATCH_LIMIT && aAction != "move")
|
||||
BMDS.endUpdateBatch();
|
||||
},
|
||||
|
||||
moveAndCheckSelection: function (aAction, aSelection, aTarget)
|
||||
@ -1697,8 +1716,15 @@ var BookmarksUtils = {
|
||||
|
||||
moveSelection: function (aAction, aSelection, aTarget)
|
||||
{
|
||||
var txn = new BookmarkMoveTransaction(aAction, aSelection, aTarget);
|
||||
BMSVC.transactionManager.doTransaction(txn);
|
||||
if (aSelection.length > kBATCH_LIMIT)
|
||||
BMDS.beginUpdateBatch();
|
||||
|
||||
gBkmkTxnSvc.startBatch();
|
||||
BookmarksUtils.removeSelection("move", aSelection);
|
||||
BookmarksUtils.insertSelection("move", aSelection, aTarget);
|
||||
gBkmkTxnSvc.endBatch();
|
||||
if (aSelection.length > kBATCH_LIMIT)
|
||||
BMDS.endUpdateBatch();
|
||||
},
|
||||
|
||||
// returns true if this selection should be copied instead of moved,
|
||||
@ -1918,297 +1944,8 @@ var BookmarksUtils = {
|
||||
}
|
||||
}
|
||||
|
||||
function BookmarkTransaction()
|
||||
{
|
||||
}
|
||||
|
||||
BookmarkTransaction.prototype = {
|
||||
BATCH_LIMIT : 4,
|
||||
RDFC : null,
|
||||
BMDS : null,
|
||||
|
||||
QueryInterface: function (iid)
|
||||
{
|
||||
if (!iid.equals(Components.interfaces.nsITransaction) &&
|
||||
!iid.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
beginUpdateBatch: function()
|
||||
{
|
||||
if (this.item.length > this.BATCH_LIMIT) {
|
||||
this.BMDS.beginUpdateBatch();
|
||||
}
|
||||
},
|
||||
|
||||
endUpdateBatch: function()
|
||||
{
|
||||
if (this.item.length > this.BATCH_LIMIT) {
|
||||
this.BMDS.endUpdateBatch();
|
||||
}
|
||||
},
|
||||
merge : function (aTxn) {return false},
|
||||
getHelperForLanguage: function (aCount) {return null},
|
||||
getInterfaces : function (aCount) {return null},
|
||||
canCreateWrapper : function (aIID) {return "AllAccess"}
|
||||
}
|
||||
|
||||
function BookmarkInsertTransaction (aAction)
|
||||
{
|
||||
this.wrappedJSObject = this;
|
||||
this.type = "insert";
|
||||
this.action = aAction;
|
||||
this.item = null;
|
||||
this.parent = null;
|
||||
this.index = null;
|
||||
this.removedProp = null;
|
||||
this.Properties = gBmProperties;
|
||||
// move container declaration to her so it can be recognize if
|
||||
// undoTransaction is call after the BM manager is close and reopen.
|
||||
this.container = Components.classes[kRDFCContractID].createInstance(kRDFCIID);
|
||||
}
|
||||
|
||||
BookmarkInsertTransaction.prototype =
|
||||
{
|
||||
__proto__: BookmarkTransaction.prototype,
|
||||
|
||||
isTransient: false,
|
||||
|
||||
doTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=0; i<this.item.length; ++i) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
// if the index is -1, we use appendElement, and then update the
|
||||
// index so that undoTransaction can still function
|
||||
if (this.index[i] == -1) {
|
||||
this.RDFC.AppendElement(this.item[i]);
|
||||
this.index[i] = this.RDFC.GetCount();
|
||||
} else {
|
||||
#ifdef BROKEN_INSERT_CODE
|
||||
try {
|
||||
this.RDFC.InsertElementAt(this.item[i], this.index[i], true);
|
||||
} catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
|
||||
// if this failed, then we assume that we really want to append,
|
||||
// because things are out of whack until we renumber.
|
||||
this.RDFC.AppendElement(this.item[i]);
|
||||
// and then fix up the index so undo works
|
||||
this.index[i] = this.RDFC.GetCount();
|
||||
}
|
||||
#else
|
||||
this.RDFC.InsertElementAt(this.item[i], this.index[i], true);
|
||||
#endif
|
||||
}
|
||||
|
||||
// insert back all the properties
|
||||
var props = this.removedProp[i];
|
||||
if (props) {
|
||||
for (var k = 0; k < props.length; ++k) {
|
||||
for (var j = 0; j < this.Properties.length; ++j) {
|
||||
var oldValue = this.BMDS.GetTarget(props[k][0], this.Properties[j], true);
|
||||
// must check, if paste call after copy the oldvalue didn't remove.
|
||||
if (!oldValue) {
|
||||
var newValue = props[k][j+1];
|
||||
if (newValue)
|
||||
this.BMDS.Assert(props[k][0], this.Properties[j], newValue, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
undoTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
// XXXvarga Can't use |RDFC| here because it's being "reused" elsewhere.
|
||||
for (var i = this.item.length-1; i >= 0; i--) {
|
||||
this.container.Init(this.BMDS, this.parent[i]);
|
||||
|
||||
// remove all properties befor we remove the element so nsLocalSearchService
|
||||
// don't return deleted element in Search
|
||||
var props = this.removedProp[i];
|
||||
if (props){
|
||||
for (var k = 0; k < props.length; ++k) {
|
||||
for (var j = 0; j < this.Properties.length; ++j) {
|
||||
var oldValue = props[k][j+1];
|
||||
if (oldValue)
|
||||
this.BMDS.Unassert(props[k][0], this.Properties[j], oldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.container.RemoveElementAt(this.index[i], true);
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
redoTransaction: function ()
|
||||
{
|
||||
this.doTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
function BookmarkRemoveTransaction (aAction)
|
||||
{
|
||||
this.wrappedJSObject = this;
|
||||
this.type = "remove";
|
||||
this.action = aAction;
|
||||
this.item = null;
|
||||
this.parent = null;
|
||||
this.index = null;
|
||||
this.removedProp = null;
|
||||
this.Properties = gBmProperties;
|
||||
}
|
||||
|
||||
BookmarkRemoveTransaction.prototype =
|
||||
{
|
||||
__proto__: BookmarkTransaction.prototype,
|
||||
|
||||
isTransient: false,
|
||||
|
||||
doTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=0; i<this.item.length; ++i) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
|
||||
// remove all properties befor we remove the element so nsLocalSearchService
|
||||
// don't return deleted element in Search
|
||||
var props = this.removedProp[i];
|
||||
if (props) {
|
||||
for (var k = 0; k < props.length; ++k) {
|
||||
for (var j = 0; j < this.Properties.length; ++j) {
|
||||
var oldValue = props[k][j+1];
|
||||
if (oldValue)
|
||||
this.BMDS.Unassert(props[k][0], this.Properties[j], oldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.RDFC.RemoveElementAt(this.index[i], false);
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
undoTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=this.item.length-1; i>=0; i--) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.InsertElementAt(this.item[i], this.index[i], false);
|
||||
|
||||
// insert back all the properties
|
||||
var props = this.removedProp[i];
|
||||
if (props) {
|
||||
for (var k = 0; k < props.length; ++k) {
|
||||
for (var j = 0; j < this.Properties.length; ++j) {
|
||||
var newValue = props[k][j+1];
|
||||
if (newValue)
|
||||
this.BMDS.Assert(props[k][0], this.Properties[j], newValue, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
},
|
||||
|
||||
redoTransaction: function ()
|
||||
{
|
||||
this.doTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
function BookmarkMoveTransaction (aAction, aSelection, aTarget)
|
||||
{
|
||||
this.wrappedJSObject = this;
|
||||
this.type = "move";
|
||||
this.action = aAction;
|
||||
this.selection = aSelection;
|
||||
this.target = 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 () {},
|
||||
redoTransaction: function () {}
|
||||
}
|
||||
|
||||
function BookmarkImportTransaction (aAction)
|
||||
{
|
||||
this.wrappedJSObject = this;
|
||||
this.type = "import";
|
||||
this.action = aAction;
|
||||
this.item = [];
|
||||
this.parent = [];
|
||||
this.index = [];
|
||||
}
|
||||
|
||||
BookmarkImportTransaction.prototype =
|
||||
{
|
||||
__proto__: BookmarkTransaction.prototype,
|
||||
|
||||
isTransient: false,
|
||||
|
||||
doTransaction: function ()
|
||||
{
|
||||
},
|
||||
|
||||
undoTransaction: function ()
|
||||
{
|
||||
this.beginUpdateBatch();
|
||||
for (var i=this.item.length-1; i>=0; 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) {
|
||||
this.RDFC.Init(this.BMDS, this.parent[i]);
|
||||
this.RDFC.InsertElementAt(this.item[i], this.index[i], true);
|
||||
}
|
||||
this.endUpdateBatch();
|
||||
}
|
||||
}
|
||||
|
||||
var BookmarkEditMenuTxnListener =
|
||||
{
|
||||
|
||||
didDo: function (aTxmgr, aTxn)
|
||||
{
|
||||
this.updateMenuItem(aTxmgr, aTxn);
|
||||
@ -2226,7 +1963,9 @@ var BookmarkEditMenuTxnListener =
|
||||
|
||||
didMerge : function (aTxmgr, aTxn) {},
|
||||
didBeginBatch : function (aTxmgr, aTxn) {},
|
||||
didEndBatch : function (aTxmgr, aTxn) {},
|
||||
didEndBatch : function (aTxmgr, aTxn) {
|
||||
this.updateMenuItem(aTxmgr, aTxn);
|
||||
},
|
||||
willDo : function (aTxmgr, aTxn) {},
|
||||
willUndo : function (aTxmgr, aTxn) {},
|
||||
willRedo : function (aTxmgr, aTxn) {},
|
||||
@ -2234,34 +1973,43 @@ var BookmarkEditMenuTxnListener =
|
||||
willBeginBatch : function (aTxmgr, aTxn) {},
|
||||
willEndBatch : function (aTxmgr, aTxn) {},
|
||||
|
||||
updateMenuItem: function (aTxmgr, aTxn) {
|
||||
if (aTxn) {
|
||||
aTxn = aTxn.wrappedJSObject;
|
||||
if ((aTxn.type == "remove" || aTxn.type == "insert") && aTxn.action == "move")
|
||||
return;
|
||||
}
|
||||
var node, transactionNumber, transactionList, transactionLabel, action;
|
||||
updateMenuItem: function bkmkMenuListenerUpdate(aTxmgr, aTxn) {
|
||||
var node, transactionNumber, transactionList, transactionLabel, action, item;
|
||||
node = document.getElementById("cmd_undo");
|
||||
transactionNumber = aTxmgr.numberOfUndoItems;
|
||||
dump("N UNDO: "+transactionNumber+"\n")
|
||||
dump("N UNDO: "+transactionNumber+"\n");
|
||||
if (transactionNumber == 0) {
|
||||
transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_undo");
|
||||
} else {
|
||||
transactionList = aTxmgr.getUndoList();
|
||||
action = transactionList.getItem(transactionNumber-1).wrappedJSObject.action;
|
||||
transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_"+action+"_undo")
|
||||
if (!transactionList.itemIsBatch(transactionNumber-1)) {
|
||||
item = transactionList.getItem(transactionNumber-1);
|
||||
action = item.wrappedJSObject.action;
|
||||
} else {
|
||||
var childList = transactionList.getChildListForItem(transactionNumber-1);
|
||||
item = childList.getItem(0);
|
||||
action = item.wrappedJSObject.action;
|
||||
}
|
||||
transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_"+action+"_undo");
|
||||
}
|
||||
node.setAttribute("label", transactionLabel);
|
||||
|
||||
node = document.getElementById("cmd_redo");
|
||||
transactionNumber = aTxmgr.numberOfRedoItems;
|
||||
dump("N REDO: "+transactionNumber+"\n")
|
||||
dump("N REDO: "+transactionNumber+"\n");
|
||||
if (transactionNumber == 0) {
|
||||
transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_redo");
|
||||
} else {
|
||||
transactionList = aTxmgr.getRedoList();
|
||||
action = transactionList.getItem(transactionNumber-1).wrappedJSObject.action;
|
||||
transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_"+action+"_redo")
|
||||
if (!transactionList.itemIsBatch(transactionNumber-1)) {
|
||||
item = transactionList.getItem(transactionNumber-1);
|
||||
action = item.wrappedJSObject.action;
|
||||
} else {
|
||||
var childList = transactionList.getChildListForItem(transactionNumber-1);
|
||||
item = childList.getItem(0);
|
||||
action = item.wrappedJSObject.action;
|
||||
}
|
||||
transactionLabel = BookmarksUtils.getLocaleString("cmd_bm_"+action+"_redo");
|
||||
}
|
||||
node.setAttribute("label", transactionLabel);
|
||||
}
|
||||
|
@ -85,13 +85,17 @@ function Startup()
|
||||
document.getElementById("CommandUpdate_Bookmarks").setAttribute("commandupdater","true");
|
||||
bookmarksView.focus();
|
||||
|
||||
BMSVC.transactionManager.AddListener(BookmarkEditMenuTxnListener);
|
||||
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
|
||||
.getService(Components.interfaces.nsIBookmarkTransactionManager);
|
||||
bkmkTxnSvc.transactionManager.AddListener(BookmarkEditMenuTxnListener);
|
||||
|
||||
}
|
||||
|
||||
function Shutdown()
|
||||
{
|
||||
BMSVC.transactionManager.RemoveListener(BookmarkEditMenuTxnListener);
|
||||
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
|
||||
.getService(Components.interfaces.nsIBookmarkTransactionManager);
|
||||
bkmkTxnSvc.transactionManager.RemoveListener(BookmarkEditMenuTxnListener);
|
||||
// Store current window position and size in window attributes (for persistence).
|
||||
var win = document.getElementById("bookmark-window");
|
||||
win.setAttribute("x", screenX);
|
||||
|
@ -25,6 +25,7 @@
|
||||
# Ben Goodger <ben@netscape.com> (Original Author)
|
||||
# Blake Ross <blaker@nemtscape.com>
|
||||
# Pierre Chanial <chanial@noos.fr> (v 2.0)
|
||||
# Joey Minta <jminta@gmail.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
|
||||
@ -504,11 +505,30 @@
|
||||
<parameter name="aTxn"/>
|
||||
<parameter name="aDo"/>
|
||||
<body><![CDATA[
|
||||
aTxn = aTxn.wrappedJSObject;
|
||||
var type = aTxn.type;
|
||||
// Skip transactions that aggregates nested "insert" or "remove" transactions.
|
||||
if ((type == "insert") && aDo || (type == "remove") && !aDo)
|
||||
this._itemToBeToggled = aTxn.item;
|
||||
if (aTxn) {
|
||||
aTxn = aTxn.wrappedJSObject;
|
||||
var type = aTxn.type;
|
||||
// Skip transactions that aggregates nested "insert" or "remove" transactions.
|
||||
if ((type == "insert") && aDo || (type == "remove") && !aDo)
|
||||
this._itemToBeToggled = [aTxn.item];
|
||||
} else {
|
||||
var txnList;
|
||||
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
|
||||
.getService(Components.interfaces.nsIBookmarkTransactionManager);
|
||||
var txmgr = bkmkTxnSvc.transactionManager;
|
||||
if (this.bookmarkTreeTransactionListener.mLastTxnWasDo) {
|
||||
txnList = txmgr.getUndoList();
|
||||
} else {
|
||||
txnList = txmgr.getRedoList();
|
||||
}
|
||||
var items =[];
|
||||
var childList = txnList.getChildListForItem(txnList.numItems-1);
|
||||
for (var i=0; i<childList.numItems; i++) {
|
||||
items.push(childList.getItem(i).wrappedJSObject.item);
|
||||
}
|
||||
this._itemToBeToggled = items;
|
||||
}
|
||||
},
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
@ -813,21 +833,28 @@
|
||||
|
||||
mOuter: this,
|
||||
|
||||
mLastTxnWasDo: null,
|
||||
|
||||
willDo: function (aTxmgr, aTxn) {},
|
||||
didDo : function (aTxmgr, aTxn) {
|
||||
this.mLastTxnWasDo = true;
|
||||
this.mOuter.preUpdateTreeSelection(aTxn, true);
|
||||
},
|
||||
willUndo: function (aTxmgr, aTxn) {},
|
||||
didUndo : function (aTxmgr, aTxn) {
|
||||
this.mLastTxnWasDo = false;
|
||||
this.mOuter.preUpdateTreeSelection(aTxn, false);
|
||||
},
|
||||
willRedo: function (aTxmgr, aTxn) {},
|
||||
didRedo : function (aTxmgr, aTxn) {
|
||||
this.mLastTxnWasDo = true;
|
||||
this.mOuter.preUpdateTreeSelection(aTxn, true);
|
||||
},
|
||||
didMerge : function (aTxmgr, aTxn) {},
|
||||
didBeginBatch : function (aTxmgr, aTxn) {},
|
||||
didEndBatch : function (aTxmgr, aTxn) {},
|
||||
didEndBatch : function (aTxmgr, aTxn) {
|
||||
this.mOuter.preUpdateTreeSelection(aTxn, this.mLastTxnWasDo);
|
||||
},
|
||||
willMerge : function (aTxmgr, aTxn) {},
|
||||
willBeginBatch : function (aTxmgr, aTxn) {},
|
||||
willEndBatch : function (aTxmgr, aTxn) {}
|
||||
@ -925,10 +952,14 @@
|
||||
<implementation>
|
||||
<constructor>
|
||||
// Adding the transaction listener
|
||||
BMSVC.transactionManager.AddListener(this.bookmarkTreeTransactionListener);
|
||||
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
|
||||
.getService(Components.interfaces.nsIBookmarkTransactionManager);
|
||||
bkmkTxnSvc.transactionManager.AddListener(this.bookmarkTreeTransactionListener);
|
||||
</constructor>
|
||||
<destructor>
|
||||
BMSVC.transactionManager.RemoveListener(this.bookmarkTreeTransactionListener);
|
||||
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
|
||||
.getService(Components.interfaces.nsIBookmarkTransactionManager);
|
||||
bkmkTxnSvc.transactionManager.RemoveListener(this.bookmarkTreeTransactionListener);
|
||||
</destructor>
|
||||
<field name="clickCount">2</field>
|
||||
</implementation>
|
||||
|
@ -45,7 +45,8 @@ include $(DEPTH)/config/autoconf.mk
|
||||
MODULE = bookmarks
|
||||
XPIDL_MODULE = bookmarks
|
||||
|
||||
XPIDLSRCS = nsIBookmarksService.idl
|
||||
XPIDLSRCS = nsIBookmarksService.idl \
|
||||
nsIBookmarkTransactionManager.idl
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
@ -0,0 +1,130 @@
|
||||
/* -*- 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 Bookmarks transaction code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Joey Minta <jminta@gmail.com>
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* 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 nsIRDFResource;
|
||||
interface nsIRDFNode;
|
||||
interface nsITransactionManager;
|
||||
|
||||
/**
|
||||
* nsIBookmarkTransactionService is a service designed to handle
|
||||
* nsITransactions that correspond to changes in bookmarks. It is here as a
|
||||
* service so that we can keep the transactions around without holding onto
|
||||
* the whole global js scope+window.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(f6305e79-1760-4991-ab4d-a42db60f0e67)]
|
||||
interface nsIBookmarkTransactionManager : nsISupports
|
||||
{
|
||||
/**
|
||||
* Performs a new transaction according to the specified parameters
|
||||
*
|
||||
* @param aType the type of transaction being performed. Must be one
|
||||
* of the three constants defined below
|
||||
* @param aAction the action to be performed. Expected values are:
|
||||
* import, insert, move, and remove (see bookmarks.js)
|
||||
* @param aItem the rdf node the transaction is being performed on
|
||||
* @param aIndex the index of the item in its RDF Container
|
||||
* @param aParent the rdf-parent of aItem, that is, the folder it
|
||||
* should be inserted into.
|
||||
* @param aRemovedProps properties removed from the item in question
|
||||
*
|
||||
*/
|
||||
void createAndCommitTxn(in unsigned long aType,
|
||||
in aString aAction,
|
||||
in nsIRDFNode aItem,
|
||||
in long aIndex,
|
||||
in nsIRDFResource aParent,
|
||||
in unsigned long aPropCount,
|
||||
[array, size_is(aPropCount)] in nsIRDFNode aRemovedProps);
|
||||
|
||||
/**
|
||||
* Constants corresponding to the 3 different types of transactions possible
|
||||
* Note that moving bookmarks is a combination of REMOVE+INSERT
|
||||
*/
|
||||
const unsigned long IMPORT = 0;
|
||||
const unsigned long INSERT = 1;
|
||||
const unsigned long REMOVE = 2;
|
||||
|
||||
/**
|
||||
* Signals the transaction manager that a series of transactions are going to
|
||||
* be performed, but that, for the purposes of undo and redo, they should all
|
||||
* be regarded as a single transaction. That is, a single undo() call will
|
||||
* undo all of the transactions created and committed between startBatch() and
|
||||
* endBatch(). See also nsITransactionManager::beginBatch
|
||||
*
|
||||
* @note if startBatch() is called multiple times. The batch will not end
|
||||
* endBatch() has been called the same number of times.
|
||||
*/
|
||||
void startBatch();
|
||||
|
||||
/**
|
||||
* Ends the batch transaction in process, subject to the note above about
|
||||
* multiple, successive calls of startBatch(). See also
|
||||
* nsITransactionManager::endBatch
|
||||
*/
|
||||
void endBatch();
|
||||
|
||||
/**
|
||||
* Undo the last transaction in the transaction manager's stack
|
||||
*/
|
||||
void undo();
|
||||
|
||||
/**
|
||||
* Returns true if it is possible to undo a transaction at this time
|
||||
*/
|
||||
boolean canUndo();
|
||||
|
||||
/**
|
||||
* Redo the last transaction
|
||||
*/
|
||||
void redo();
|
||||
|
||||
/**
|
||||
* Returns true if it is possible to redo a transaction at this time
|
||||
*/
|
||||
boolean canRedo();
|
||||
|
||||
/**
|
||||
* A reference to the transaction manager for bookmarks
|
||||
*/
|
||||
readonly attribute nsITransactionManager transactionManager;
|
||||
|
||||
};
|
@ -46,7 +46,6 @@
|
||||
|
||||
interface nsIArray;
|
||||
interface nsIRDFResource;
|
||||
interface nsITransactionManager;
|
||||
|
||||
[scriptable, uuid(ccc48346-429d-4931-94dc-beb1afcea292)]
|
||||
interface nsIBookmarksService : nsISupports
|
||||
@ -108,8 +107,6 @@ interface nsIBookmarksService : nsISupports
|
||||
|
||||
string resolveKeyword(in wstring aName, out wstring aPostData);
|
||||
|
||||
readonly attribute nsITransactionManager transactionManager;
|
||||
|
||||
//XXXpch: to be removed.
|
||||
void addBookmarkImmediately(in wstring aURI, in wstring aTitle, in long bmType, in wstring docCharset);
|
||||
boolean isBookmarked(in string aURL);
|
||||
|
@ -73,6 +73,7 @@ CPPSRCS = nsBookmarksService.cpp \
|
||||
$(NULL)
|
||||
|
||||
#EXTRA_COMPONENTS = nsBookmarkProtocolHandler.js
|
||||
EXTRA_COMPONENTS = nsBookmarkTransactionManager.js
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
|
373
browser/components/bookmarks/src/nsBookmarkTransactionManager.js
Normal file
373
browser/components/bookmarks/src/nsBookmarkTransactionManager.js
Normal file
@ -0,0 +1,373 @@
|
||||
/* ***** 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 bookmark transaction code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Joey Minta <jminta@gmail.com>
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* 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 bookmarkTransactionManager() {
|
||||
this.wrappedJSObject = this;
|
||||
this.mTransactionManager = Components.classes["@mozilla.org/transactionmanager;1"]
|
||||
.createInstance(Components.interfaces.nsITransactionManager);
|
||||
|
||||
this.mBatchCount = 0;
|
||||
|
||||
this.classInfo = {
|
||||
getInterfaces: function (count) {
|
||||
var ifaces = [
|
||||
Components.interfaces.nsISupports,
|
||||
Components.interfaces.nsIClassInfo
|
||||
];
|
||||
count.value = ifaces.length;
|
||||
return ifaces;
|
||||
},
|
||||
|
||||
getHelperForLanguage: function (language) {
|
||||
return null;
|
||||
},
|
||||
|
||||
contractID: "@mozilla.org/bookmarks/transactionManager;1",
|
||||
classDescription: "Booksmarks Transaction Manager",
|
||||
classID: Components.ID("{62d2f7fb-acd2-4876-aa2d-b607de9329ff}"),
|
||||
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
|
||||
flags: 0
|
||||
};
|
||||
|
||||
// Define our transactions
|
||||
function bkmkTxn() {
|
||||
this.item = null;
|
||||
this.parent = null;
|
||||
this.index = null;
|
||||
this.removedProp = null;
|
||||
};
|
||||
|
||||
bkmkTxn.prototype = {
|
||||
BMDS: null,
|
||||
|
||||
QueryInterface: function bkmkTxnQI(iid) {
|
||||
if (!iid.equals(Components.interfaces.nsITransaction) &&
|
||||
!iid.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
merge : function (aTxn) {return false},
|
||||
getHelperForLanguage: function (aCount) {return null},
|
||||
getInterfaces : function (aCount) {return null},
|
||||
canCreateWrapper : function (aIID) {return "AllAccess"},
|
||||
|
||||
mAssertProperties: function bkmkTxnAssertProps(aProps) {
|
||||
if (!aProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
for each (var prop in aProps) {
|
||||
for (var i = 0; i < this.Properties.length; i++) {
|
||||
var oldValue = this.BMDS.GetTarget(this.item, this.Properties[i], true);
|
||||
// must check, if paste call after copy the oldvalue didn't remove.
|
||||
if (!oldValue) {
|
||||
var newValue = aProps[i+1];
|
||||
if (newValue) {
|
||||
this.BMDS.Assert(this.item,
|
||||
this.Properties[i],
|
||||
newValue, true);
|
||||
}
|
||||
} else {
|
||||
this.removedProp[i+1] = oldValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mUnassertProperties: function bkmkTxnUnassertProps(aProps) {
|
||||
if (!aProps) {
|
||||
return;
|
||||
}
|
||||
for each (var prop in aProps) {
|
||||
for (var i = 0; i < this.Properties.length; i++) {
|
||||
var oldValue = aProps[i+1];
|
||||
if (oldValue) {
|
||||
this.BMDS.Unassert(this.item, this.Properties[i], oldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bkmkTxn.prototype.RDFC =
|
||||
Components.classes["@mozilla.org/rdf/container;1"]
|
||||
.createInstance(Components.interfaces.nsIRDFContainer);
|
||||
var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"]
|
||||
.getService(Components.interfaces.nsIRDFService);
|
||||
bkmkTxn.prototype.BMDS = rdfService.GetDataSource("rdf:bookmarks");
|
||||
|
||||
bkmkTxn.prototype.Properties =
|
||||
[rdfService.GetResource("http://home.netscape.com/NC-rdf#Name"),
|
||||
rdfService.GetResource("http://home.netscape.com/NC-rdf#URL"),
|
||||
rdfService.GetResource("http://home.netscape.com/NC-rdf#ShortcutURL"),
|
||||
rdfService.GetResource("http://home.netscape.com/NC-rdf#Description"),
|
||||
rdfService.GetResource("http://home.netscape.com/NC-rdf#WebPanel"),
|
||||
rdfService.GetResource("http://home.netscape.com/NC-rdf#FeedURL")];
|
||||
|
||||
function bkmkInsertTxn(aAction) {
|
||||
this.type = "insert";
|
||||
// move container declaration to here so it can be recognized if
|
||||
// undoTransaction is call after the BM manager is close and reopen.
|
||||
this.container = Components.classes["@mozilla.org/rdf/container;1"]
|
||||
.createInstance(Components.interfaces.nsIRDFContainer);
|
||||
}
|
||||
|
||||
bkmkInsertTxn.prototype = {
|
||||
__proto__: bkmkTxn.prototype,
|
||||
|
||||
isTransient: false,
|
||||
|
||||
doTransaction: function bkmkInsertDoTxn() {
|
||||
this.RDFC.Init(this.BMDS, this.parent);
|
||||
// if the index is -1, we use appendElement, and then update the
|
||||
// index so that undoTransaction can still function
|
||||
if (this.index == -1) {
|
||||
this.RDFC.AppendElement(this.item);
|
||||
this.index = this.RDFC.GetCount();
|
||||
} else {
|
||||
/*XXX- broken insert code, see bug 264571
|
||||
try {
|
||||
this.RDFC.InsertElementAt(this.item, this.index, true);
|
||||
} catch (e if e.result == Components.results.NS_ERROR_ILLEGAL_VALUE) {
|
||||
// if this failed, then we assume that we really want to append,
|
||||
// because things are out of whack until we renumber.
|
||||
this.RDFC.AppendElement(this.item);
|
||||
// and then fix up the index so undo works
|
||||
this.index = this.RDFC.GetCount();
|
||||
}
|
||||
*/
|
||||
this.RDFC.InsertElementAt(this.item, this.index, true);
|
||||
}
|
||||
|
||||
// insert back all the properties
|
||||
this.mAssertProperties(this.removedProp);
|
||||
},
|
||||
|
||||
undoTransaction: function bkmkInsertUndoTxn() {
|
||||
// XXXvarga Can't use |RDFC| here because it's being "reused" elsewhere.
|
||||
this.container.Init(this.BMDS, this.parent);
|
||||
|
||||
// remove all properties befor we remove the element so
|
||||
// nsLocalSearchService doesn't return deleted element in Search
|
||||
this.mUnassertProperties(this.removedProp);
|
||||
|
||||
this.container.RemoveElementAt(this.index, true);
|
||||
},
|
||||
|
||||
redoTransaction: function bkmkInsertRedoTxn() {
|
||||
this.doTransaction();
|
||||
}
|
||||
};
|
||||
|
||||
function bkmkRemoveTxn() {
|
||||
this.type = "remove";
|
||||
}
|
||||
|
||||
bkmkRemoveTxn.prototype = {
|
||||
__proto__: bkmkTxn.prototype,
|
||||
|
||||
isTransient: false,
|
||||
|
||||
doTransaction: function bkmkRemoveDoTxn() {
|
||||
this.RDFC.Init(this.BMDS, this.parent);
|
||||
|
||||
// remove all properties befor we remove the element so
|
||||
// nsLocalSearchService doesn't return deleted element in Search
|
||||
this.mUnassertProperties(this.removedProp);
|
||||
|
||||
this.RDFC.RemoveElementAt(this.index, false);
|
||||
},
|
||||
|
||||
undoTransaction: function bkmkRemoveUndoTxn() {
|
||||
this.RDFC.Init(this.BMDS, this.parent);
|
||||
this.RDFC.InsertElementAt(this.item, this.index, false);
|
||||
|
||||
// insert back all the properties
|
||||
this.mAssertProperties(this.removedProp);
|
||||
},
|
||||
|
||||
redoTransaction: function () {
|
||||
this.doTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
function bkmkImportTxn(aAction) {
|
||||
this.type = "import";
|
||||
this.action = aAction;
|
||||
}
|
||||
|
||||
bkmkImportTxn.prototype = {
|
||||
__proto__: bkmkTxn.prototype,
|
||||
|
||||
isTransient: false,
|
||||
|
||||
doTransaction: function bkmkImportDoTxn() {},
|
||||
|
||||
undoTransaction: function mkmkImportUndoTxn() {
|
||||
this.RDFC.Init(this.BMDS, this.parent);
|
||||
this.RDFC.RemoveElementAt(this.index, true);
|
||||
},
|
||||
|
||||
redoTransaction: function bkmkImportredoTxn() {
|
||||
this.RDFC.Init(this.BMDS, this.parent);
|
||||
this.RDFC.InsertElementAt(this.item, this.index, true);
|
||||
}
|
||||
};
|
||||
|
||||
this.BookmarkRemoveTransaction = bkmkRemoveTxn;
|
||||
this.BookmarkInsertTransaction = bkmkInsertTxn;
|
||||
this.BookmarkImportTransaction = bkmkImportTxn;
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.QueryInterface = function bkTxnMgrQI(aIID) {
|
||||
if (aIID.equals(Components.interfaces.nsISupports) ||
|
||||
aIID.equals(Components.interfaces.nsIBookmarkTransactionManager)) {
|
||||
return this;
|
||||
}
|
||||
if (aIID.equals(Components.interfaces.nsIClassInfo)) {
|
||||
return this.classInfo;
|
||||
}
|
||||
|
||||
throw NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.createAndCommitTxn =
|
||||
function bkmkTxnMgrCandC(aType, aAction, aItem, aIndex, aParent, aPropCount, aRemovedProps) {
|
||||
var txn;
|
||||
var nsIBookmarkTransactionManager = Components.interfaces.nsIBookmarkTransactionManager;
|
||||
switch (aType) {
|
||||
case nsIBookmarkTransactionManager.IMPORT:
|
||||
txn = new this.BookmarkImportTransaction(aAction);
|
||||
break;
|
||||
case nsIBookmarkTransactionManager.INSERT:
|
||||
txn = new this.BookmarkInsertTransaction(aAction);
|
||||
break;
|
||||
case nsIBookmarkTransactionManager.REMOVE:
|
||||
txn = new this.BookmarkRemoveTransaction(aAction);
|
||||
break;
|
||||
default:
|
||||
Components.utils.reportError("Unknown bookmark transaction type:"+aType);
|
||||
throw NS_ERROR_FAILURE;
|
||||
}
|
||||
txn.item = aItem;
|
||||
txn.parent = aParent;
|
||||
txn.index = aIndex;
|
||||
txn.removedProp = aRemovedProps;
|
||||
txn.action = aAction;
|
||||
txn.wrappedJSObject = txn;
|
||||
this.mTransactionManager.doTransaction(txn);
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.startBatch = function bkmkTxnMgrUndo() {
|
||||
if (this.mBatchCount == 0) {
|
||||
this.mTransactionManager.beginBatch();
|
||||
}
|
||||
this.mBatchCount++;
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.endBatch = function bkmkTxnMgrUndo() {
|
||||
this.mBatchCount--;
|
||||
if (this.mBatchCount == 0) {
|
||||
this.mTransactionManager.endBatch();
|
||||
}
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.undo = function bkmkTxnMgrUndo() {
|
||||
this.mTransactionManager.undoTransaction();
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.redo = function bkmkTxnMgrRedo() {
|
||||
this.mTransactionManager.redoTransaction();
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.canUndo = function bkmkTxnMgrCanUndo() {
|
||||
return this.mTransactionManager.numberOfUndoItems > 0;
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.canRedo = function bkmkTxnMgrCanRedo() {
|
||||
return this.mTransactionManager.numberOfRedoItems > 0;
|
||||
}
|
||||
|
||||
bookmarkTransactionManager.prototype.__defineGetter__("transactionManager",
|
||||
function bkmkTxnMgrGetter() { return this.mTransactionManager; });
|
||||
|
||||
/****
|
||||
**** module registration
|
||||
****/
|
||||
|
||||
const kFactory = {
|
||||
createInstance: function (outer, iid) {
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return (new bookmarkTransactionManager()).QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
|
||||
var bkmkTxnMgrModule = {
|
||||
mCID: Components.ID("{8be133d0-681d-4f0b-972b-6a68e41afb62}"),
|
||||
mContractID: "@mozilla.org/bookmarks/transactionmanager;1",
|
||||
|
||||
registerSelf: function (compMgr, fileSpec, location, type) {
|
||||
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
||||
compMgr.registerFactoryLocation(this.mCID,
|
||||
"Bookmark Transaction Manager",
|
||||
this.mContractID,
|
||||
fileSpec,
|
||||
location,
|
||||
type);
|
||||
},
|
||||
|
||||
getClassObject: function (compMgr, cid, iid) {
|
||||
if (!cid.equals(this.mCID))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
|
||||
if (!iid.equals(Components.interfaces.nsIFactory))
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
return kFactory;
|
||||
},
|
||||
|
||||
canUnload: function(compMgr) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
function NSGetModule(compMgr, fileSpec) {
|
||||
return bkmkTxnMgrModule;
|
||||
}
|
@ -1698,9 +1698,6 @@ nsBookmarksService::Init()
|
||||
nsICache::STREAM_BASED, getter_AddRefs(mCacheSession));
|
||||
}
|
||||
|
||||
mTransactionManager = do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
/* create a URL for the string resource file */
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_SUCCEEDED(rv = mNetService->NewURI(bookmark_properties, nsnull, nsnull,
|
||||
@ -3531,15 +3528,6 @@ nsBookmarksService::ResolveKeyword(const PRUnichar *aUserInput, PRUnichar** aPos
|
||||
return NS_RDF_NO_VALUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::GetTransactionManager(nsITransactionManager** aTransactionManager)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTransactionManager);
|
||||
|
||||
NS_ADDREF(*aTransactionManager = mTransactionManager);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBookmarksService::GetBookmarksToolbarFolder(nsIRDFResource** aResult)
|
||||
{
|
||||
|
@ -56,7 +56,6 @@
|
||||
#include "nsIIOService.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsITransactionManager.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
|
||||
class nsIOutputStream;
|
||||
@ -84,7 +83,6 @@ protected:
|
||||
nsCOMPtr<nsIIOService> mNetService;
|
||||
nsCOMPtr<nsICacheService> mCacheService;
|
||||
nsCOMPtr<nsICacheSession> mCacheSession;
|
||||
nsCOMPtr<nsITransactionManager> mTransactionManager;
|
||||
|
||||
PRUint32 htmlSize;
|
||||
PRInt32 mUpdateBatchNest;
|
||||
|
Loading…
Reference in New Issue
Block a user