From abc6a9eccd62b4c1805be6dbd12b1979b4e409ba Mon Sep 17 00:00:00 2001 From: "joe%retrovirus.com" Date: Tue, 4 Apr 2006 01:26:58 +0000 Subject: [PATCH] Implements "Bookmark All Tabs..." for Places. (Also fixes a small error when undoing aggregate transactions.) bug=330929 r=annie.sullivan@gmail.com sr=ben@mozilla.org git-svn-id: svn://10.0.0.236/trunk@193476 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/browser/base/content/browser-sets.inc | 1 + mozilla/browser/base/content/browser.js | 38 +++- .../places/content/bookmarkProperties.js | 190 ++++++++++++++---- .../components/places/content/controller.js | 24 ++- .../browser/places/bookmarkProperties.dtd | 1 + .../places/bookmarkProperties.properties | 2 + 6 files changed, 203 insertions(+), 53 deletions(-) diff --git a/mozilla/browser/base/content/browser-sets.inc b/mozilla/browser/base/content/browser-sets.inc index 4ac3715de41..ec55c4da81b 100644 --- a/mozilla/browser/base/content/browser-sets.inc +++ b/mozilla/browser/base/content/browser-sets.inc @@ -148,6 +148,7 @@ #ifdef MOZ_PLACES + #else diff --git a/mozilla/browser/base/content/browser.js b/mozilla/browser/base/content/browser.js index 25bab03bac5..a06288136e2 100644 --- a/mozilla/browser/base/content/browser.js +++ b/mozilla/browser/base/content/browser.js @@ -6294,12 +6294,44 @@ function BookmarkAllTabsCommand() { } BookmarkAllTabsCommand.prototype = { get enabled() { - //LOG("BookmarkAllTabs.enabled: " + getBrowser().tabContainer.childNodes.length > 1); return getBrowser().tabContainer.childNodes.length > 1; }, - + execute: function BATC_execute() { - LOG("BookmarkAllTabs.execute: IMPLEMENT ME"); + var tabURIs = this._getUniqueTabInfo(getBrowser()); + PlacesController.showAddMultiBookmarkUI(tabURIs); + }, + + /** + * This function returns a list of nsIURI objects characterizing the + * tabs currently open in the given browser. The URIs will appear in the + * list in the order in which their corresponding tabs appeared. However, + * only the first instance of each URI will be returned. + * + * @param aTabBrowser the tabBrowser to get the contents of + * + * @returns a list of nsIURI objects representing unique locations open + */ + _getUniqueTabInfo: function BATC__getUniqueTabInfo(aTabBrowser) { + var tabList = []; + var seenURIs = []; + + const activeBrowser = aTabBrowser.selectedBrowser; + const browsers = aTabBrowser.browsers; + for (var i = 0; i < browsers.length; ++i) { + var webNav = browsers[i].webNavigation; + var uri = webNav.currentURI; + + // skip redundant entries + if (uri.spec in seenURIs) + continue; + + // add to the set of seen URIs + seenURIs[uri.spec] = true; + + tabList.push(uri); + } + return tabList; } }; BookmarkAllTabsCommand.NAME = "Browser:BookmarkAllTabs"; diff --git a/mozilla/browser/components/places/content/bookmarkProperties.js b/mozilla/browser/components/places/content/bookmarkProperties.js index 47d9b1188f8..c1efa65e705 100755 --- a/mozilla/browser/components/places/content/bookmarkProperties.js +++ b/mozilla/browser/components/places/content/bookmarkProperties.js @@ -100,6 +100,7 @@ var BookmarkPropertiesPanel = { ADD_BOOKMARK_VARIANT: 1, EDIT_HISTORY_VARIANT: 2, EDIT_FOLDER_VARIANT: 3, + ADD_MULTIPLE_BOOKMARKS_VARIANT: 4, /** * The variant identifier for the current instance of the dialog. @@ -118,8 +119,25 @@ var BookmarkPropertiesPanel = { _identifierIsURI: function BPP__identifierIsURI() { switch(this._variant) { - case this.EDIT_FOLDER_VARIANT: return false; - default: return true; + case this.EDIT_FOLDER_VARIANT: + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + return false; + default: + return true; + } + }, + + /** + * Returns true if this variant of the dialog uses a folder ID as a primary + * identifier for the item being edited. + */ + + _identifierIsFolderID: function BPP__identifierIsFolderID() { + switch(this._variant) { + case this.EDIT_FOLDER_VARIANT: + return true; + default: + return false; } }, @@ -128,8 +146,10 @@ var BookmarkPropertiesPanel = { */ _isTitleEditable: function BPP__isTitleEditable() { switch(this._variant) { - case this.EDIT_HISTORY_VARIANT: return false; - default: return true; + case this.EDIT_HISTORY_VARIANT: + return false; + default: + return true; } }, @@ -138,9 +158,12 @@ var BookmarkPropertiesPanel = { */ _isURIEditable: function BPP__isURIEditable() { switch(this._variant) { - case this.EDIT_HISTORY_VARIANT: return false; - case this.EDIT_FOLDER_VARIANT: return false; - default: return true; + case this.EDIT_HISTORY_VARIANT: + case this.EDIT_FOLDER_VARIANT: + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + return false; + default: + return true; } }, @@ -149,8 +172,11 @@ var BookmarkPropertiesPanel = { */ _isURIVisible: function BPP__isURIVisible() { switch(this._variant) { - case this.EDIT_FOLDER_VARIANT: return false; - default: return true; + case this.EDIT_FOLDER_VARIANT: + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + return false; + default: + return true; } }, @@ -160,9 +186,12 @@ var BookmarkPropertiesPanel = { */ _isShortcutVisible: function BPP__isShortcutVisible() { switch(this._variant) { - case this.EDIT_HISTORY_VARIANT: return false; - case this.EDIT_FOLDER_VARIANT: return false; - default: return true; + case this.EDIT_HISTORY_VARIANT: + case this.EDIT_FOLDER_VARIANT: + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + return false; + default: + return true; } }, @@ -172,10 +201,13 @@ var BookmarkPropertiesPanel = { */ _isDeletePossible: function BPP__isDeletePossible() { switch(this._variant) { - case this.EDIT_HISTORY_VARIANT: return false; - case this.ADD_BOOKMARK_VARIANT: return false; - case this.EDIT_FOLDER_VARIANT: return false; - default: return true; + case this.EDIT_HISTORY_VARIANT: + case this.ADD_BOOKMARK_VARIANT: + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + case this.EDIT_FOLDER_VARIANT: + return false; + default: + return true; } }, @@ -183,10 +215,13 @@ var BookmarkPropertiesPanel = { * Returns true if the URI's folder is editable in this variant * of the dialog. */ - _isFolderEditable: function BPP__isFolderVisible() { + _isFolderEditable: function BPP__isFolderEditable() { switch(this._variant) { - case this.ADD_BOOKMARK_VARIANT: return true; - default: return false; + case this.ADD_BOOKMARK_VARIANT: + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + return true; + default: + return false; } }, @@ -198,7 +233,10 @@ var BookmarkPropertiesPanel = { switch(this._variant) { case this.ADD_BOOKMARK_VARIANT: return this._strings.getString("dialogAcceptLabelAdd"); - default: return this._strings.getString("dialogAcceptLabelEdit"); + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + return this._strings.getString("dialogAcceptLabelAddMulti"); + default: + return this._strings.getString("dialogAcceptLabelEdit"); } }, @@ -214,11 +252,31 @@ var BookmarkPropertiesPanel = { return this._strings.getString("dialogTitleHistoryEdit"); case this.EDIT_FOLDER_VARIANT: return this._strings.getString("dialogTitleFolderEdit"); + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + return this._strings.getString("dialogTitleAddMulti"); default: return this._strings.getString("dialogTitleBookmarkEdit"); } }, + /** + * Returns a string representing the folder tree selection type for + * the given dialog variant. This is either "single" when you can only + * select one folder (usually because we're dealing with the location + * of a child folder, which can only have one parent), or "multiple" + * when you can select multiple folders (bookmarks can be in multiple + * folders). + */ + _getFolderSelectionType: function BPP__getFolderSelectionType() { + switch(this._variant) { + case this.ADD_MULTIPLE_BOOKMARKS_VARIANT: + case this.EDIT_FOLDER_VARIANT: + return "single"; + default: + return "multiple"; + } + }, + /** * This method can be run on a URI parameter to ensure that it didn't * receive a string instead of an nsIURI object. @@ -239,7 +297,8 @@ var BookmarkPropertiesPanel = { * @param identifier the URI or folder ID to display the properties for * @param action -- "add" if this is being triggered from an "add bookmark" * UI action; or "edit" if this is being triggered from - * a "properties" UI action + * a "properties" UI action; or "addmulti" if we're + * trying to create multiple bookmarks * * @returns one of the *_VARIANT constants */ @@ -253,6 +312,9 @@ var BookmarkPropertiesPanel = { return this.ADD_BOOKMARK_VARIANT; } } + else if (action == "addmulti") { + return this.ADD_MULTIPLE_BOOKMARKS_VARIANT; + } else { /* Assume "edit" */ if (typeof(identifier) == "number") return this.EDIT_FOLDER_VARIANT; @@ -266,6 +328,33 @@ var BookmarkPropertiesPanel = { } }, + /** + * This method returns the title string corresponding to a given URI. + * If none is available from the bookmark service (probably because + * the given URI doesn't appear in bookmarks or history), we synthesize + * a title from the first 100 characters of the URI. + * + * @param uri a nsIURI object for which we want the title + * + * @returns a title string + */ + + _getURITitle: function BPP__getURITitle(uri) { + this._assertURINotString(uri); + + var title = this._bms.getItemTitle(uri); + + /* If we can't get a title for a new bookmark, let's set it to + be the first 100 characters of the URI. */ + if (title == null) { + title = uri.spec; + if (title.length > 100) { + title = title.substr(0, 100); + } + } + return title; + }, + /** * This method should be called by the onload of the Bookmark Properties * dialog to initialize the state of the panel. @@ -284,9 +373,12 @@ var BookmarkPropertiesPanel = { this._assertURINotString(identifier); this._bookmarkURI = identifier; } - else { + else if (this._identifierIsFolderID()){ this._folderId = identifier; } + else if (this._isVariant(this.ADD_MULTIPLE_BOOKMARKS_VARIANT)) { + this._URIList = identifier; + } this._dialogWindow = dialogWindow; this._controller = controller; @@ -307,6 +399,7 @@ var BookmarkPropertiesPanel = { this._folderTree.peerDropTypes = []; this._folderTree.childDropTypes = []; this._folderTree.excludeItems = true; + this._folderTree.setAttribute("seltype", this._getFolderSelectionType()); var query = this._hist.getNewQuery(); query.setFolders([this._bms.placesRoot], 1); @@ -324,18 +417,9 @@ var BookmarkPropertiesPanel = { var document = this._dialogWindow.document; if (this._identifierIsURI()) { - this._bookmarkTitle = this._bms.getItemTitle(this._bookmarkURI); - - /* If we can't get a title for a new bookmark, let's set it to - be the first 100 characters of the URI. */ - if (this._isVariant(this.ADD_BOOKMARK_VARIANT) && !this._bookmarkTitle) { - this._bookmarkTitle = this._bookmarkURI.spec; - if (this._bookmarkTitle.length > 100) { - this._bookmarkTitle = this._bookmarkTitle.substr(0, 100); - } - } + this._bookmarkTitle = this._getURITitle(this._bookmarkURI); } - else { + else if (this._identifierIsFolderID()){ this._bookmarkTitle = this._bms.getFolderTitle(this._folderId); } @@ -458,6 +542,7 @@ var BookmarkPropertiesPanel = { _saveChanges: function PBD_saveChanges() { var transactions = []; var urlbox = this._dialogWindow.document.getElementById("editURLBar"); + var titlebox = this._dialogWindow.document.getElementById("editTitleBox"); var newURI = this._bookmarkURI; if (this._identifierIsURI() && this._isURIEditable()) newURI = this._uri(urlbox.value); @@ -465,24 +550,45 @@ var BookmarkPropertiesPanel = { if (this._isFolderEditable()) { var selected = this._folderTree.getSelectionNodes(); - for (var i = 0; i < selected.length; i++) { - var node = selected[i]; - if (node.type == node.RESULT_TYPE_FOLDER) { - var folder = node.QueryInterface(Ci.nsINavHistoryFolderResultNode); - if (!folder.childrenReadOnly) { - transactions.push( - new PlacesCreateItemTransaction(newURI, folder.folderId, -1)); + if (this._identifierIsURI()) { + for (var i = 0; i < selected.length; i++) { + var node = selected[i]; + if (node.type == node.RESULT_TYPE_FOLDER) { + var folder = node.QueryInterface(Ci.nsINavHistoryFolderResultNode); + if (!folder.childrenReadOnly) { + transactions.push( + new PlacesCreateItemTransaction(newURI, folder.folderId, -1)); + } } } } + else if (this._isVariant(this.ADD_MULTIPLE_BOOKMARKS_VARIANT)) { + var node = selected[0]; + var folder = node.QueryInterface(Ci.nsINavHistoryFolderResultNode); + + var newFolderTrans = new PlacesCreateFolderTransaction( + titlebox.value, folder.folderId, -1); + + var childTransactions = []; + for (var i = 0; i < this._URIList.length; ++i) { + var uri = this._URIList[i]; + childTransactions.push( + new PlacesCreateItemTransaction(uri, -1, -1)); + childTransactions.push( + new PlacesEditItemTitleTransaction(uri, + this._getURITitle(uri))); + } + newFolderTrans.childTransactions = childTransactions; + + transactions.push(newFolderTrans); + } } - var titlebox = this._dialogWindow.document.getElementById("editTitleBox"); if (this._identifierIsURI()) transactions.push( new PlacesEditItemTitleTransaction(newURI, titlebox.value)); - else + else if (this._identifierIsFolderID()) transactions.push( new PlacesEditFolderTitleTransaction(this._folderId, titlebox.value)); diff --git a/mozilla/browser/components/places/content/controller.js b/mozilla/browser/components/places/content/controller.js index dc0b71f819b..18ad72dbfef 100755 --- a/mozilla/browser/components/places/content/controller.js +++ b/mozilla/browser/components/places/content/controller.js @@ -1205,6 +1205,19 @@ var PlacesController = { this._showBookmarkDialog(uri, "add"); }, + /** + * Show an "Add Bookmarks" dialog to allow the adding of a folder full + * of bookmarks corresponding to the objects in the uriList. This will + * be called most often as the result of a "Bookmark All Tabs..." command. + * + * @param uriList List of nsIURI objects representing the locations + * to be bookmarked. + */ + showAddMultiBookmarkUI: function PC_showAddMultiBookmarkUI(uriList) { + NS_ASSERT(uriList.length, "showAddMultiBookmarkUI expects a list of nsIURI objects"); + this._showBookmarkDialog(uriList, "addmulti"); + }, + /** * Opens the bookmark properties panel for a given URI. * @@ -1231,17 +1244,12 @@ var PlacesController = { * This is an implementation function, and shouldn't be called directly; * rather, use the specific variant above that corresponds to your situation. * - * @param identifier the URI or folder ID to show the dialog for + * @param identifier the URI or folder ID or URI list to show + * properties for * @param action "add" or "edit", see _determineVariant in * bookmarkProperties.js */ _showBookmarkDialog: function PC__showBookmarkDialog(identifier, action) { - // The identifier parameter can be either an integer (for folders) or - // a nsIURI object (for bookmarks/history items); if it isn't a number - // here, we're going to make sure it's a URI object rather than a string. - if (typeof(identifier) != "number") - this._assertURINotString(identifier); - window.openDialog("chrome://browser/content/places/bookmarkProperties.xul", "", "width=600,height=400,chrome,dependent,modal,resizable", identifier, this, action); @@ -2218,7 +2226,7 @@ PlacesAggregateTransaction.prototype = { undoTransaction: function() { this.LOG("== UN" + this._name + " (UNAggregate) ============"); this.bookmarks.beginUpdateBatch(); - for (var i = this._transactions.length; i >= 0; --i) { + for (var i = this._transactions.length - 1; i >= 0; --i) { var txn = this._transactions[i]; if (this.container > -1) txn.container = this.container; diff --git a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd index d167626b930..4d73893222b 100644 --- a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd +++ b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.dtd @@ -19,3 +19,4 @@ + diff --git a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties index 4e0ffd4af27..6b93d2b9a4e 100644 --- a/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties +++ b/mozilla/browser/locales/en-US/chrome/browser/places/bookmarkProperties.properties @@ -1,6 +1,8 @@ dialogAcceptLabelAdd=Add Bookmark +dialogAcceptLabelAddMulti=Add Bookmarks dialogAcceptLabelEdit=Save Changes dialogTitleAdd=Add Bookmark +dialogTitleAddMulti=Bookmark All Tabs dialogTitleBookmarkEdit=Bookmark Properties dialogTitleHistoryEdit=Viewed Page Properties dialogTitleFolderEdit=Edit Folder Properties