From 9d50ee9317162e86fc6a264017af49609f1495c6 Mon Sep 17 00:00:00 2001 From: Simon Kornblith Date: Thu, 3 Feb 2011 07:04:14 +0000 Subject: [PATCH] closes #1750: Show determinate progress bars for import/export --- chrome/content/zotero/fileInterface.js | 17 +++-- .../xpcom/translation/browser_firefox.js | 7 ++ .../zotero/xpcom/translation/item_local.js | 8 ++- .../zotero/xpcom/translation/translate.js | 63 +++++++++++++++++- chrome/content/zotero/xpcom/zotero.js | 65 +++++++++++-------- chrome/content/zotero/zoteroPane.js | 5 +- translators/MODS.js | 8 ++- translators/RDF.js | 6 +- 8 files changed, 141 insertions(+), 38 deletions(-) diff --git a/chrome/content/zotero/fileInterface.js b/chrome/content/zotero/fileInterface.js index f32d8f090..22b0ffa16 100644 --- a/chrome/content/zotero/fileInterface.js +++ b/chrome/content/zotero/fileInterface.js @@ -41,7 +41,7 @@ var Zotero_File_Exporter = function() { * Performs the actual export operation **/ Zotero_File_Exporter.prototype.save = function() { - var translation = new Zotero.Translate("export"); + var translation = new Zotero.Translate.Export(); var translators = translation.getTranslators(); // present options dialog @@ -81,6 +81,7 @@ Zotero_File_Exporter.prototype.save = function() { translation.setLocation(fp.file); translation.setTranslator(io.selectedTranslator); translation.setDisplayOptions(io.displayOptions); + translation.setHandler("itemDone", Zotero_File_Interface.updateProgress); translation.setHandler("done", this._exportDone); Zotero.UnresponsiveScriptIndicator.disable(); Zotero_File_Interface.Progress.show( @@ -171,7 +172,7 @@ var Zotero_File_Interface = new function() { * exports items to clipboard */ function exportItemsToClipboard(items, translatorID) { - var translation = new Zotero.Translate("export"); + var translation = new Zotero.Translate.Export(); translation.setItems(items); translation.setTranslator(translatorID); translation.setHandler("done", _copyToClipboard); @@ -195,7 +196,7 @@ var Zotero_File_Interface = new function() { * Creates Zotero.Translate instance and shows file picker for file import */ function importFile() { - var translation = new Zotero.Translate("import"); + var translation = new Zotero.Translate.Import(); var translators = translation.getTranslators(); const nsIFilePicker = Components.interfaces.nsIFilePicker; @@ -248,7 +249,7 @@ var Zotero_File_Interface = new function() { return; } - var translate = new Zotero.Translate("import"); + var translate = new Zotero.Translate.Import(); translate.setString(str); translate.setHandler("translators", function(obj, item) { _importTranslatorsAvailable(obj, item) @@ -280,6 +281,7 @@ var Zotero_File_Interface = new function() { // import items translation.setTranslator(translators[0]); translation.setHandler("collectionDone", _importCollectionDone); + translation.setHandler("itemDone", Zotero_File_Interface.updateProgress); translation.setHandler("done", _importDone); Zotero.UnresponsiveScriptIndicator.disable(); @@ -604,6 +606,13 @@ var Zotero_File_Interface = new function() { return false; } } + + /** + * Updates progress indicators based on current progress of translation + */ + this.updateProgress = function(translate) { + Zotero.updateZoteroPaneProgressMeter(translate.progress); + } } // Handles the display of a progress indicator diff --git a/chrome/content/zotero/xpcom/translation/browser_firefox.js b/chrome/content/zotero/xpcom/translation/browser_firefox.js index fa12908f1..bbc830a2f 100644 --- a/chrome/content/zotero/xpcom/translation/browser_firefox.js +++ b/chrome/content/zotero/xpcom/translation/browser_firefox.js @@ -265,6 +265,7 @@ Zotero.Translate.IO.Read.prototype = { "_seekToStart":function() { this._rawStream.QueryInterface(Components.interfaces.nsISeekableStream) .seek(Components.interfaces.nsISeekableStream.NS_SEEK_SET, this._bomLength); + this.bytesRead = this._bomLength; }, "_readToString":function() { @@ -323,6 +324,7 @@ Zotero.Translate.IO.Read.prototype = { } if(amountRead) { + this.bytesRead += amountRead; return str.value; } else { return false; @@ -364,6 +366,11 @@ Zotero.Translate.IO.Read.prototype = { } } +Zotero.Translate.IO.String.prototype.__defineGetter__("contentLength", +function() { + return this.file.fileSize; +}); + /******* Write support *******/ Zotero.Translate.IO.Write = function(file, mode, charset) { diff --git a/chrome/content/zotero/xpcom/translation/item_local.js b/chrome/content/zotero/xpcom/translation/item_local.js index bb99f9fcf..187b0e483 100644 --- a/chrome/content/zotero/xpcom/translation/item_local.js +++ b/chrome/content/zotero/xpcom/translation/item_local.js @@ -503,6 +503,7 @@ Zotero.Translate.ItemGetter = function() { Zotero.Translate.ItemGetter.prototype = { "setItems":function(items) { this._itemsLeft = items; + this.numItems = this._itemsLeft.length; }, "setCollection":function(collection, getChildCollections) { @@ -531,6 +532,8 @@ Zotero.Translate.ItemGetter.prototype = { } } } + + this.numItems = this._itemsLeft.length; }, "setAll":function(getChildCollections) { @@ -539,6 +542,8 @@ Zotero.Translate.ItemGetter.prototype = { if(getChildCollections) { this._collectionsLeft = Zotero.getCollections(); } + + this.numItems = this._itemsLeft.length; }, "exportFiles":function(dir, extension) { @@ -712,4 +717,5 @@ Zotero.Translate.ItemGetter.prototype = { obj.name = obj.fields.name; return obj; } -} \ No newline at end of file +} +Zotero.Translate.ItemGetter.prototype.__defineGetter__("numItemsRemaining", function() { return this._itemsLeft.length }); \ No newline at end of file diff --git a/chrome/content/zotero/xpcom/translation/translate.js b/chrome/content/zotero/xpcom/translation/translate.js index 9bbd1d0ae..5b57caf2e 100644 --- a/chrome/content/zotero/xpcom/translation/translate.js +++ b/chrome/content/zotero/xpcom/translation/translate.js @@ -96,6 +96,7 @@ Zotero.Translate.Sandbox = { // // This can probably be re-enabled for web translators once badly asynced ones are fixed if (translate instanceof Zotero.Translate.Import || translate instanceof Zotero.Translate.Export) { + Zotero.debug("waiting"); Zotero.wait(); } @@ -381,6 +382,20 @@ Zotero.Translate.Sandbox = { "_collectionDone":function(translate, collection) { var newCollection = translate._itemSaver.saveCollection(collection); translate._runHandler("collectionDone", newCollection); + }, + + /** + * Sets the value of the progress indicator associated with export as a percentage + * @param {Zotero.Translate} translate + * @param {Number} value + */ + "setProgress":function(translate, value) { + if(typeof value !== "number") { + translate._progress = null; + } else { + translate._progress = value; + } + Zotero.debug("setting progress to "+value); } }, @@ -417,6 +432,13 @@ Zotero.Translate.Sandbox = { } return translate._itemGetter.nextCollection(); + }, + + /** + * @borrows Zotero.Translate.Sandbox.Import.setProgress as this.setProgress + */ + "setProgress":function(translate, value) { + Zotero.Translate.Sandbox.Import.setProgress(translate, value); } }, @@ -1039,7 +1061,10 @@ Zotero.Translate.Import.prototype.setString = function(string) { * Overload {@link Zotero.Translate.Base#complete} to close file */ Zotero.Translate.Import.prototype.complete = function(returnValue, error) { - if(this._currentState == "translate" && this._io) this._io.close(); + if(this._currentState == "translate" && this._io) { + this._progress = null; + this._io.close(); + } // call super Zotero.Translate.Base.prototype.complete.apply(this, [returnValue, error]); @@ -1127,11 +1152,25 @@ Zotero.Translate.Import.prototype._loadTranslator = function(translator) { * Prepare translation */ Zotero.Translate.Import.prototype._prepareTranslation = function(libraryID, saveAttachments) { + this._progress = undefined; this._itemSaver = new Zotero.Translate.ItemSaver(libraryID, Zotero.Translate.ItemSaver[(saveAttachments ? "ATTACHMENT_MODE_FILE" : "ATTACHMENT_MODE_IGNORE")]); this.newItems = this._itemSaver.newItems; this.newCollections = this._itemSaver.newCollections; } + +Zotero.Translate.Import.prototype.__defineGetter__("progress", +/** + * Return the progress of the import operation, or null if progress cannot be determined + */ +function() { + Zotero.debug("progress is "+this._progress); + if(this._progress !== undefined) return this._progress; + if(Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1 || this._mode === "xml/e4x" || this._mode == "xml/dom" || !this._io) { + return null; + } + return this._io.bytesRead/this._io.contentLength*100; +}); Zotero.Translate.Export = function() { @@ -1199,6 +1238,8 @@ Zotero.Translate.Export.prototype._detect = function() { * Does the actual export, after code has been loaded and parsed */ Zotero.Translate.Export.prototype._prepareTranslation = function(libraryID, saveAttachments) { + this._progress = undefined; + // initialize ItemGetter this._itemGetter = new Zotero.Translate.ItemGetter(); var getCollections = this.translator[0].configOptions.getCollections ? this.translator[0].configOptions.getCollections : false; @@ -1232,6 +1273,18 @@ Zotero.Translate.Export.prototype._prepareTranslation = function(libraryID, save this._sandboxManager.importObject(this._io); } +Zotero.Translate.Export.prototype.__defineGetter__("progress", +/** + * Return the progress of the import operation, or null if progress cannot be determined + */ +function() { + if(this._progress !== undefined) return this._progress; + if(!this._itemGetter) { + return null; + } + return (1-this._itemGetter.numItemsRemaining/this._itemGetter.numItems)*100; +}); + /** * @property {Array[]} search Item (in {@link Zotero.Item#serialize} format) to extrapolate data * (set with setSearch) @@ -1488,6 +1541,14 @@ Zotero.Translate.IO.String.prototype.__defineSetter__("string", function(string) { this._string = string; }); +Zotero.Translate.IO.String.prototype.__defineGetter__("bytesRead", +function() { + return this._stringPointer; +}); +Zotero.Translate.IO.String.prototype.__defineGetter__("contentLength", +function() { + return this._string.length; +}); /****** RDF DATA MODE ******/ diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index b01e296b9..d93277556 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -1378,15 +1378,19 @@ var Zotero = new function(){ * @return void */ this.showZoteroPaneProgressMeter = function (msg, determinate) { + Zotero.debug("showing progress meter"); var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator); var enumerator = wm.getEnumerator("navigator:browser"); var progressMeters = []; while (enumerator.hasMoreElements()) { var win = enumerator.getNext(); + Zotero.debug("win found"); + if(!win.ZoteroPane) continue; + Zotero.debug("win has pane"); - win.document.getElementById('zotero-pane-progress-label').value = msg; - var progressMeter = win.document.getElementById('zotero-pane-progressmeter') + win.ZoteroPane.document.getElementById('zotero-pane-progress-label').value = msg; + var progressMeter = win.ZoteroPane.document.getElementById('zotero-pane-progressmeter') if (determinate) { progressMeter.mode = 'determined'; progressMeter.value = 0; @@ -1396,10 +1400,11 @@ var Zotero = new function(){ progressMeter.mode = 'undetermined'; } - _showWindowZoteroPaneOverlay(win); - win.document.getElementById('zotero-pane-overlay-deck').selectedIndex = 0; + _showWindowZoteroPaneOverlay(win.ZoteroPane.document); + win.ZoteroPane.document.getElementById('zotero-pane-overlay-deck').selectedIndex = 0; progressMeters.push(progressMeter); + Zotero.debug("added meter for win"); } _locked = true; _progressMeters = progressMeters; @@ -1410,20 +1415,26 @@ var Zotero = new function(){ * @param {Number} percentage Percentage complete as integer or float */ this.updateZoteroPaneProgressMeter = function (percentage) { - if (percentage < 0 || percentage > 100) { - Zotero.debug("Invalid percentage value '" + percentage + "' in Zotero.updateZoteroPaneProgressMeter()"); - return; + if(percentage !== null) { + if (percentage < 0 || percentage > 100) { + Zotero.debug("Invalid percentage value '" + percentage + "' in Zotero.updateZoteroPaneProgressMeter()"); + return; + } + percentage = Math.round(percentage * 10); } - percentage = Math.round(percentage * 10); - if (percentage == _lastPercentage) { + if (percentage === _lastPercentage) { return; } for each(var pm in _progressMeters) { - if (pm.mode == 'undetermined') { - pm.max = 1000; - pm.mode = 'determined'; + if (percentage !== null) { + if (pm.mode == 'undetermined') { + pm.max = 1000; + pm.mode = 'determined'; + } + pm.value = percentage; + } else if(pm.mode === 'determined') { + pm.mode = 'undetermined'; } - pm.value = percentage; } _lastPercentage = percentage; } @@ -1446,7 +1457,9 @@ var Zotero = new function(){ var enumerator = wm.getEnumerator("navigator:browser"); while (enumerator.hasMoreElements()) { var win = enumerator.getNext(); - _hideWindowZoteroPaneOverlay(win); + if(win.ZoteroPane && win.ZoteroPane.document) { + _hideWindowZoteroPaneOverlay(win.ZoteroPane.document); + } } _locked = false; _progressMeters = []; @@ -1468,21 +1481,21 @@ var Zotero = new function(){ } - function _showWindowZoteroPaneOverlay(win) { - win.document.getElementById('zotero-collections-tree').disabled = true; - win.document.getElementById('zotero-items-tree').disabled = true; - win.document.getElementById('zotero-pane-tab-catcher-top').hidden = false; - win.document.getElementById('zotero-pane-tab-catcher-bottom').hidden = false; - win.document.getElementById('zotero-pane-overlay').hidden = false; + function _showWindowZoteroPaneOverlay(doc) { + doc.getElementById('zotero-collections-tree').disabled = true; + doc.getElementById('zotero-items-tree').disabled = true; + doc.getElementById('zotero-pane-tab-catcher-top').hidden = false; + doc.getElementById('zotero-pane-tab-catcher-bottom').hidden = false; + doc.getElementById('zotero-pane-overlay').hidden = false; } - function _hideWindowZoteroPaneOverlay(win) { - win.document.getElementById('zotero-collections-tree').disabled = false; - win.document.getElementById('zotero-items-tree').disabled = false; - win.document.getElementById('zotero-pane-tab-catcher-top').hidden = true; - win.document.getElementById('zotero-pane-tab-catcher-bottom').hidden = true; - win.document.getElementById('zotero-pane-overlay').hidden = true; + function _hideWindowZoteroPaneOverlay(doc) { + doc.getElementById('zotero-collections-tree').disabled = false; + doc.getElementById('zotero-items-tree').disabled = false; + doc.getElementById('zotero-pane-tab-catcher-top').hidden = true; + doc.getElementById('zotero-pane-tab-catcher-bottom').hidden = true; + doc.getElementById('zotero-pane-overlay').hidden = true; } diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 229c5b6b2..5786aa16f 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -98,6 +98,7 @@ var ZoteroPane = new function() */ function init() { + this.document = document; if(!Zotero || !Zotero.initialized) return; // Set "Report Errors..." label via property rather than DTD entity, @@ -509,7 +510,7 @@ var ZoteroPane = new function() catch (e) { Zotero.debug(e); } - if(ZoteroOverlay) ZoteroOverlay.toggleDisplay() + if(window.ZoteroOverlay) window.ZoteroOverlay.toggleDisplay() break; case 'library': document.getElementById('zotero-collections-tree').focus(); @@ -3398,7 +3399,7 @@ var ZoteroPane = new function() * if necessary. */ this.show = function() { - if(ZoteroOverlay) { + if(window.ZoteroOverlay) { if(ZoteroOverlay.isTab) { ZoteroOverlay.loadZoteroTab(); } else if(!this.isShowing()) { diff --git a/translators/MODS.js b/translators/MODS.js index b324def8d..cfa0f56c3 100644 --- a/translators/MODS.js +++ b/translators/MODS.js @@ -10,7 +10,7 @@ "configOptions":{"dataMode":"xml/e4x"}, "displayOptions":{"exportNotes":true}, "inRepository":true, - "lastUpdated":"2011-02-02 05:01:48" + "lastUpdated":"2011-02-03 07:00:12" } function detectImport() { @@ -484,10 +484,13 @@ function doImport() { if(xml.m::mods.length()) { var modsElements = xml.m::mods; + var nModsElements = modsElements.length(); } else { var modsElements = [xml]; + var nModsElements = 1; } + var i = 0; for each(var mods in modsElements) { var newItem = new Zotero.Item(); @@ -746,8 +749,7 @@ function doImport() { // join the list separated by semicolons & add it to zotero item newItem.language = languages.join('; '); - Zotero.debug(newItem); - + Zotero.setProgress(i++/nModsElements*100); newItem.complete(); } } diff --git a/translators/RDF.js b/translators/RDF.js index d0ea1f7f2..822efc3ae 100644 --- a/translators/RDF.js +++ b/translators/RDF.js @@ -9,7 +9,7 @@ "priority":100, "configOptions":{"dataMode":"rdf/xml"}, "inRepository":true, - "lastUpdated":"2011-01-11 04:31:00" + "lastUpdated":"2011-02-03 07:00:12" } function detectImport() { @@ -578,6 +578,7 @@ function importItem(newItem, node, type) { } function doImport() { + Zotero.setProgress(null); var nodes = Zotero.RDF.getAllResources(); if(!nodes) { return false; @@ -586,6 +587,7 @@ function doImport() { // keep track of collections while we're looping through var collections = new Array(); + var i = 0; for each(var node in nodes) { var newItem = new Zotero.Item(); newItem.itemID = Zotero.RDF.getResourceURI(node); @@ -618,6 +620,8 @@ function doImport() { if(importItem(newItem, node, type)) { newItem.complete(); } + + Zotero.setProgress(i++/nodes.length*100); } /* COLLECTIONS */