%bookmarksDTD; ]> "http://www.w3.org/1999/02/22-rdf-syntax-ns#" "http://home.netscape.com/NC-rdf#" this.NC_NS + "command?cmd="; null null null // see bug 63370 for details var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] .getService(Components.interfaces.nsILocaleService); var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService); var bundleURL = "chrome://communicator/locale/bookmarks/bookmark.properties"; this._bundle = stringBundleService.createBundle(bundleURL, localeService.GetApplicationLocale()); // setTimeout(this.refreshSort, 0, this); ]]> = rangeMin.value; --j) { var level = bo.view.getLevel(j); if (level <= currLevel) { currLevel = level; lastIndex = j; } } } return lastIndex; ]]> = 0; --i) { var rangeMin = { }; var rangeMax = { }; this.mOuter.outlinerBoxObject.selection.getRangeAt(i, rangeMin, rangeMax); for (var j = rangeMax.value; j >= rangeMin.value; --j) { var currRes = this.mOuter.outlinerBuilder.getResourceAtIndex(j); var parentIndex = this.mOuter.outlinerBoxObject.view.getParentIndex(j); var parentRes; if (parentIndex == -1) parentRes = this.mOuter.rdf.GetResource("NC:BookmarksRoot"); else parentRes = this.mOuter.outlinerBuilder.getResourceAtIndex(parentIndex); var type = this.mOuter.db.GetTarget(currRes, this.mOuter.rdf.GetResource(this.mOuter.RDF_NS + "type"), true); type = type.QueryInterface(Components.interfaces.nsIRDFResource).Value; if (!type || (type != (this.mOuter.NC_NS + "BookmarkSeparator") && type != (this.mOuter.NC_NS + "Bookmark") && type != (this.mOuter.NC_NS + "Folder"))) throw Components.results.NS_OK; var name = this.mOuter.db.GetTarget(currRes, this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "Name"), true); var data = new TransferData(); if (name) { name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value; data.addDataForFlavour("text/x-moz-url", currRes.Value + "\n" + name); } else { data.addDataForFlavour("text/x-moz-url", currRes.Value); } data.addDataForFlavour("moz/rdfitem", currRes.Value + "\n" + parentRes.Value); data.addDataForFlavour("text/unicode", currRes.Value); aXferData.data.push(data); } if (aEvent.ctrlKey) { const kDSIID = Components.interfaces.nsIDragService; aDragAction.action = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK; } } } }) ]]> 0; case "cmd_bm_find": return true; case "cmd_bm_newbookmark": case "cmd_bm_newfolder": case "cmd_bm_newseparator": // This is not really correct because it gives the false impression // that it is possible to create an item as a child of some immutable folders // like IE Favorites, but it will do for now. return true; case "cmd_bm_delete": // Determining whether or not the selection is mutable is handled by // the deletion routine. type = this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex); if (type != this.mOuter.NC_NS + "Bookmark" && type != this.mOuter.NC_NS + "BookmarkSeparator" && type != this.mOuter.NC_NS + "Folder") return false; return bo.selection.count >= 1; case "cmd_bm_selectAll": // "Select All" is disabled when all visible rows are selected. // XXXben this could be cleverer. return bo.view.rowCount != bo.selection.count; case "cmd_bm_copy": return bo.selection.count >= 1; case "cmd_bm_paste": return this.mOuter.canPaste(); case "cmd_bm_openfolderinnewwindow": if (bo.selection.count != 1) return false; return this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex) == this.mOuter.NC_NS + "Folder"; case "cmd_bm_setnewbookmarkfolder": case "cmd_bm_setpersonaltoolbarfolder": case "cmd_bm_setnewsearchfolder": if (bo.selection.count != 1) return false; // XXXbar if a folder has more than one of these special attributes, // this won't work var folderURI; if (aCommand == "cmd_bm_setnewbookmarkfolder") folderURI = "NC:NewBookmarkFolder"; else if (aCommand == "cmd_bm_setpersonaltoolbarfolder") folderURI = "NC:PersonalToolbarFolder"; else folderURI = "NC:NewSearchFolder"; return (this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex) == this.mOuter.NC_NS + "Folder") && (this.mOuter.outlinerBuilder.getResourceAtIndex(this.mOuter.firstSelectedIndex).Value != folderURI); case "cmd_bm_import": case "cmd_bm_export": return true; case "cmd_bm_fileBookmark": if (bo.selection.count < 1) return false; type = this.mOuter.getTypeAtIndex(this.mOuter.firstSelectedIndex); return type == this.mOuter.NC_NS + "Folder" || type == this.mOuter.NC_NS + "Bookmark"; default: return false; } }, doCommand: function BMOLController_doCommand(aCommand) { switch (aCommand) { case "cmd_bm_cut": this.mOuter.copySelection(); this.mOuter.deleteSelection(); break; case "cmd_bm_copy": this.mOuter.copySelection(); break; case "cmd_bm_paste": this.mOuter.paste(); break; case "cmd_bm_delete": this.mOuter.deleteSelection(); break; case "cmd_bm_selectAll": this.mOuter.selectAll(); break; case "cmd_bm_open": this.mOuter.openItem(); break; case "cmd_bm_openfolder": this.mOuter.outlinerBoxObject.view.toggleOpenState(this.mOuter.currentIndex); break; case "cmd_bm_openfolderinnewwindow": this.mOuter.openFolderInNewWindow(); break; case "cmd_bm_newbookmark": this.mOuter.addBookmark(); break; case "cmd_bm_newfolder": this.mOuter.createNewFolder(); break; case "cmd_bm_newseparator": this.mOuter.createNewSeparator(); break; case "cmd_bm_find": this.mOuter.openFindDialog(); break; case "cmd_bm_properties": case "cmd_bm_rename": this.mOuter.openPropertiesForItem(); break; case "cmd_bm_setnewbookmarkfolder": this.mOuter.setAsNewBookmarkFolder(); break; case "cmd_bm_setpersonaltoolbarfolder": this.mOuter.setAsPersonalToolbarFolder(); break; case "cmd_bm_setnewsearchfolder": this.mOuter.setAsNewSearchFolder(); break; case "cmd_bm_import": this.mOuter.importBookmarks(); break; case "cmd_bm_export": this.mOuter.exportBookmarks(); break; case "cmd_bm_fileBookmark": this.mOuter.fileBookmark(); break; default: } } }) ]]> = 0 ? (parentID[i] = sourceUri.substr(ix+1), sourceUri.substr(0, ix)) : sourceUri; break; case "text/x-moz-url": ix = sourceUri.indexOf("\n"); sourceID[i] = ix >= 0 ? (name[i] = sourceUri.substr(ix+1), sourceUri.substr(0, ix)) : sourceUri; break; case "text/unicode": sourceID[i] = sourceUri; nameRequired[i] = true; break; default: continue; } var rSource = this.mOuter.rdf.GetResource(sourceID[i]); var rParent = parentID[i] ? this.mOuter.rdf.GetResource(parentID[i]) : null; const kBMDS = this.mOuter.bookmarksDS; RDFC.Init(kBMDS, rContainer); var dropIx = RDFC.IndexOf(rTarget); // XXX if any of the following fails, the nodes are gone for good! const kDSIID = Components.interfaces.nsIDragService; const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK; if (rParent) { if (!(dragSession.dragAction & kCopyAction)) { try { RDFC.Init(kBMDS, rParent); ix = RDFC.IndexOf(rSource); if (ix >= 1) RDFC.RemoveElementAt(ix, true); } catch (ex) { } } } var bmType = kBMDS.GetTarget(this.mOuter.rdf.GetResource(sourceID[i]), this.mOuter.rdf.GetResource(this.mOuter.RDF_NS + "type"), true); var rType = this.mOuter.rdf.GetResource(this.mOuter.RDF_NS + "type"); if (!bmType) kBMDS.Assert(rSource, rType, rBookmark, true); if (bmType == this.mOuter.NC_NS + "Folder") { // If we're going to copy a folder type, we need to clone the folder // rather than just asserting the new node as a child of the drop folder. if (dragSession.dragAction & kCopyAction) rSource = BookmarksUtils.cloneFolder(rSource, rContainer, rTarget); } if (orientation == this.inDropBefore || orientation == this.inDropAfter) { if (dropIx == -1) break; RDFC.Init(kBMDS, rContainer); RDFC.InsertElementAt(rSource, rParent ? dropIx : (orientation == this.inDropAfter ? ++dropIx : dropIx), true); } else { rContainer = this.mOuter.outlinerBuilder.getResourceAtIndex(row); RDFC.Init(kBMDS, rContainer); RDFC.AppendElement(rSource); // drop on } dirty = true; //if (rParent) { // gBookmarksShell.selectFolderItem(rContainer.Value, sourceID[i], additiveFlag); // if (!additiveFlag) additiveFlag = true; //} // If a name is supplied, we want to assert this information into the // graph. E.g. user drags an internet shortcut to the app, we want to // preserve not only the URL but the name of the shortcut. The other case // where we need to assert a name is when the node does not already exist // in the graph, in this case we'll just use the URL as the name. if (name[i] || nameRequired[i]) { var currentName = kBMDS.GetTarget(this.mOuter.rdf.GetResource(sourceID[i]), this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "Name"), true); if (!currentName) { var rDefaultName = this.mOuter.rdf.GetLiteral(name[i] || sourceID[i]); if (rDefaultName) { var rName = this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "Name"); kBMDS.Assert(rSource, rName, rDefaultName, true); } } } if (dirty) this.mOuter.flushBMDatasource(); } }, onToggleOpenState: function BMOLBuilderObserver_onToggleOpenState(aItemIndex) { }, onCycleHeader: function BMOLBuilderObserver_onCycleHeader(aColumnID, aHeaderElement) { }, onCycleCell: function BMOLBuilderObserver_onCycleCell(aItemIndex, aColumnID) { }, onSelectionChanged: function BMOLBuilderObserver_onSelectionChanged() { this.mOuter.onCommandUpdate(); const kStatusBar = document.getAnonymousElementByAttribute(this.mOuter, "anonid", "statusbar-text"); const currentIndex = this.mOuter.currentIndex; var displayValue = ""; if (kStatusBar && this.mOuter.outlinerBoxObject.selection.count == 1) { if (this.mOuter.outlinerBoxObject.view.isContainer(currentIndex)) { const kRDFCContractID = "@mozilla.org/rdf/container;1"; const kRDFCIID = Components.interfaces.nsIRDFContainer; const kRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID); const krSrc = this.mOuter.outlinerBuilder.getResourceAtIndex(currentIndex); try { kRDFC.Init(this.mOuter.db, krSrc); var count = kRDFC.GetCount(); displayValue = this.mOuter._bundle.GetStringFromName("status_foldercount"); displayValue = displayValue.replace(/%num_items%/, count); } catch (e) { } } else { try { displayValue = this.mOuter.db.GetTarget(this.mOuter.outlinerBuilder.getResourceAtIndex(currentIndex), this.mOuter.rdf.GetResource(this.mOuter.NC_NS + "URL"), true); displayValue = displayValue.QueryInterface(Components.interfaces.nsIRDFLiteral).Value; } catch (e) { displayValue = ""; } } if (displayValue.substring(0, 3) == "NC:") displayValue = ""; kStatusBar.label = displayValue; } }, isEditable: function BMOLBuilderObserver_isEditable(aItemIndex, aColumnID) { }, onSetCellText: function BMOLBuilderObserver_onSetCellText(aItemIndex, aColumnID, aValue) { }, onPerformAction: function BMOLBuilderObserver_onPerformAction(aAction) { }, onPerformActionOnRow: function BMOLBuilderObserver_onPerformActionOnRow(aAction, aItemIndex) { }, onPerformActionOnCell: function BMOLBuilderObserver_onPerformActionOnCell(aAction, aItemIndex, aColumnID) { } }) ]]> = 0; --i) { var rangeMin = {}; var rangeMax = {}; this.outlinerBoxObject.selection.getRangeAt(i, rangeMin, rangeMax); for (var j = rangeMax.value; j >= rangeMin.value; --j) { var res = this.outlinerBuilder.getResourceAtIndex(j); var urlRes = ksRDF.GetResource("http://home.netscape.com/NC-rdf#URL"); var nameRes = ksRDF.GetResource("http://home.netscape.com/NC-rdf#Name"); var url = this.db.GetTarget(res, urlRes, true); if (url) url = url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value; var name = this.db.GetTarget(res, nameRes, true); name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value; // XXXben is "\n" the best delimiter here? I think not. sBookmarkItem += res.Value + "\n"; sTextUnicode += url + "\n"; sTextHTML += "" + name + ""; } } const kXferableContractID = "@mozilla.org/widget/transferable;1"; const kXferableIID = Components.interfaces.nsITransferable; var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID); xferable.addDataFlavor("moz/bookmarkclipboarditem"); bmstring.data = sBookmarkItem; xferable.setTransferData("moz/bookmarkclipboarditem", bmstring, sBookmarkItem.length*2) xferable.addDataFlavor("text/html"); htmlstring.data = sTextHTML; xferable.setTransferData("text/html", htmlstring, sTextHTML.length*2) xferable.addDataFlavor("text/unicode"); unicodestring.data = sTextUnicode; xferable.setTransferData("text/unicode", unicodestring, sTextUnicode.length*2) const kClipboardContractID = "@mozilla.org/widget/clipboard;1"; const kClipboardIID = Components.interfaces.nsIClipboard; var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID); clipboard.setData(xferable, null, kClipboardIID.kGlobalClipboard); ]]> = 0; --i) { boxObject.selection.getRangeAt(i, rangeMin, rangeMax); for (var j = rangeMax.value; j >= rangeMin.value; --j) { var resource = outlinerBuilder.getResourceAtIndex(j); var type = this.getTypeAtIndex(j); if (resource.Value == "NC:BookmarksRoot" || type == this.NC_NS + "IEFavoriteFolder") continue; if (type != this.NC_NS + "Bookmark" && type != this.NC_NS + "BookmarkSeparator" && type != this.NC_NS + "Folder") { // This delete operation contains items which cannot be deleted // for one reason or another. Make a list of the items which // we can't delete, and show a dialog. container.AppendElement(resource); selectionContainsImmutableItems = true; // Now we need to ensure that this item's parent chain is not // part of the current selection so that we don't delete that. We // preserve selection on any deletable items in the folder chain // however, and these are removed. for (var parentIndex = boxObject.view.getParentIndex(j); parentIndex != -1; parentIndex = boxObject.view.getParentIndex(parentIndex)) { // Note that we don't combine this with the check in the // |while| above, as this would mean that if you had a folder // hierarchy consisting of: // // Folder -> [ selected ] // Folder -> [ not selected ] // Immutable item [ selected ] // // This code would not work and the containing folder would be // deleted. if (boxObject.selection.isSelected(parentIndex)) boxObject.selection.toggleSelect(parentIndex); } } } } // Present a dialog showing any items that we can't delete. // if (selectionContainsImmutableItems) { // openDialog("chrome://communicator/content/bookmarks/deleteBookmark.xul", "", "modal=yes,resizable=no", imDS); // Now clear the list of immutable items. ksRDFC.Init(imDS, immutableList); var count = ksRDFC.GetCount(); for (var i = 0; i < count; ++i) ksRDFC.RemoveElementAt(i, false); } */ for (i = rangeCount - 1; i >= 0; --i) { rangeMax = { }; rangeMin = { }; boxObject.selection.getRangeAt(i, rangeMin, rangeMax); for (var j = rangeMax.value; j >= rangeMin.value; --j) { var resource = outlinerBuilder.getResourceAtIndex(j); if (resource.Value == "NC:BookmarksRoot") continue; var currType = this.getTypeAtIndex(j); if (currType == this.NC_NS + "IEFavoriteFolder") { const kPrefSvcContractID = "@mozilla.org/preferences;1"; const kPrefSvcIID = Components.interfaces.nsIPref; const kPrefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID); kPrefSvc.SetBoolPref("browser.bookmarks.import_system_favorites", false); } else if (currType != this.NC_NS + "Bookmark" && currType != this.NC_NS + "BookmarkSeparator" && currType != this.NC_NS + "Folder") continue; var parentIndex = boxObject.view.getParentIndex(j); var parent; if (parentIndex != -1) parent = outlinerBuilder.getResourceAtIndex(parentIndex); else { // assume its parent is the root parent = ksRDF.GetResource("NC:BookmarksRoot"); } ksRDFC.Init(this.bookmarksDS, parent); ksRDFC.RemoveElement(resource, true); nextIndex = j; } } // Select the next row boxObject.selection.select(nextIndex); ]]> 0 && common[common.length-1] == aNewArray[i]) continue; if (aNewArray[i] == aOldArray[j]) common.push(aNewArray[i]); } } return common; ]]> // will throw, we'll catch & stifle the error, and look up the command // name in the datasource. return this._bundle.GetStringFromName("cmd_" + cmdName); } catch (e) { // XXX - WORK TO DO HERE! (rjc will cry if we don't fix this) // need to ask the ds for the commands for this node, however we don't // have the right params. This is kind of a problem. dump("*** BAD! EVIL! WICKED! NO! ACK! ARGH! ORGH!\n"); const rName = this.rdf.GetResource(this.NC_NS + "Name"); const rSource = this.rdf.GetResource(aCommand); return this.db.GetTarget(rSource, rName, true).Value; } ]]> = 0; --i) { var minRange = {}; var maxRange = {}; this.outlinerBoxObject.selection.getRangeAt(i, minRange, maxRange); for (var j = maxRange.value; j >= minRange.value; --j) { var nodeURI = this.outlinerBuilder.getResourceAtIndex(j).Value; var commands = this.getAllCmds(nodeURI); if (!commands) { aEvent.preventDefault(); return; } commands = this.flattenEnumerator(commands); if (!commonCommands.length) commonCommands = commands; commonCommands = this.findCommonNodes(commands, commonCommands); } } if (!commonCommands.length) { aEvent.preventDefault(); return; } // Now that we should have generated a list of commands that is valid // for the entire selection, build a context menu. for (i = 0; i < commonCommands.length; ++i) { const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var currCommand = commonCommands[i].QueryInterface(Components.interfaces.nsIRDFResource).Value; var element = null; if (currCommand != this.NC_NS_CMD + "bm_separator") { var commandName = this.getCommandName(currCommand); var selectedIndex = this.outlinerBoxObject.selection.currentIndex; element = this.createMenuItem(commandName, currCommand, selectedIndex); } else if (i != 0 && i < commonCommands.length-1) { // Never append a separator as the first or last element in a context // menu. element = document.createElementNS(kXULNS, "menuseparator"); } if (element) popup.appendChild(element); } ]]> = 0; --k) { var rangeMin = {}; var rangeMax = {}; this.outlinerBoxObject.selection.getRangeAt(k, rangeMin, rangeMax); for (var i = rangeMax.value; i >= rangeMin.value; --i) { var selected = this.outlinerBuilder.getResourceAtIndex(i); if (selected.Value == rv.selectedFolder) return; // Selection contains the target folder. Just fail silently. var additiveFlag = false; var parentIndex = this.outlinerBoxObject.view.getParentIndex(i); var parentURI; if (parentIndex == -1) parentURI = this.rdf.GetResource("NC:BookmarksRoot").Value; else parentURI = this.outlinerBuilder.getResourceAtIndex(parentIndex).Value; this.moveBookmark(selected.Value, parentURI, rv.selectedFolder); // gBookmarksShell.selectFolderItem(rv.selectedFolder, selected.Value, additiveFlag); if (!additiveFlag) additiveFlag = true; } } this.flushBMDatasource(); } ]]>