diff --git a/chrome/content/zotero/browser.js b/chrome/content/zotero/browser.js
index cbd073644d..fce82cda86 100644
--- a/chrome/content/zotero/browser.js
+++ b/chrome/content/zotero/browser.js
@@ -120,6 +120,17 @@ var Zotero_Browser = new function() {
* @return void
*/
function scrapeThisPage(libraryID, collectionID) {
+ if (Zotero.locked) {
+ Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
+ // TODO: localize
+ var desc = "A Zotero operation is currently in progress. Please wait until it finishes and try again.";
+ Zotero_Browser.progress.addDescription(desc);
+ Zotero_Browser.progress.show();
+ Zotero_Browser.progress.startCloseTimer(8000);
+ return;
+ return;
+ }
+
if (!Zotero.stateCheck()) {
Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
var desc = Zotero.getString("ingester.scrapeError.transactionInProgress.previousError")
diff --git a/chrome/content/zotero/fileInterface.js b/chrome/content/zotero/fileInterface.js
index 7fce01c010..402d571b89 100644
--- a/chrome/content/zotero/fileInterface.js
+++ b/chrome/content/zotero/fileInterface.js
@@ -80,10 +80,9 @@ Zotero_File_Exporter.prototype.save = function() {
translation.setHandler("done", this._exportDone);
Zotero.UnresponsiveScriptIndicator.disable();
Zotero_File_Interface.Progress.show(
- Zotero.getString("fileInterface.itemsExported"),
- function() {
- translation.translate();
- });
+ Zotero.getString("fileInterface.itemsExported")
+ );
+ translation.translate()
}
return false;
}
@@ -269,13 +268,10 @@ var Zotero_File_Interface = new function() {
// show progress indicator
Zotero_File_Interface.Progress.show(
- Zotero.getString("fileInterface.itemsImported"),
- function() {
- Zotero.DB.beginTransaction();
-
- // translate
- translation.translate();
- });
+ Zotero.getString("fileInterface.itemsImported")
+ );
+ Zotero.DB.beginTransaction();
+ translation.translate();
} else {
var prompt = Components.classes["@mozilla.org/network/default-prompt;1"]
.getService(Components.interfaces.nsIPrompt);
@@ -569,50 +565,14 @@ var Zotero_File_Interface = new function() {
// Handles the display of a progress indicator
Zotero_File_Interface.Progress = new function() {
- var _windowLoaded = false;
- var _windowLoading = false;
- var _progressWindow;
- // keep track of all of these things in case they're called before we're
- // done loading the progress window
- var _loadHeadline, _loadNumber, _outOf, _callback;
-
this.show = show;
this.close = close;
- function show(headline, callback) {
- if(_windowLoading || _windowLoaded) { // already loading or loaded
- _progressWindow.focus();
- return false;
- }
- _windowLoading = true;
-
- _loadHeadline = headline;
- _loadNumber = 0;
- _outOf = 0;
- _callback = callback;
-
- _progressWindow = window.openDialog("chrome://zotero/content/fileProgress.xul", "", "chrome,resizable=no,close=no,dependent,dialog,centerscreen");
- _progressWindow.addEventListener("pageshow", _onWindowLoaded, false);
-
- return true;
+ function show(headline) {
+ Zotero.showZoteroPaneProgressBar(headline)
}
function close() {
- _windowLoaded = false;
- try {
- _progressWindow.close();
- } catch(ex) {}
- }
-
- function _onWindowLoaded() {
- _windowLoading = false;
- _windowLoaded = true;
-
- // do things we delayed because the winodw was loading
- _progressWindow.document.getElementById("progress-label").value = _loadHeadline;
-
- if(_callback) {
- window.setTimeout(_callback, 1500);
- }
+ Zotero.hideZoteroPaneOverlay();
}
}
\ No newline at end of file
diff --git a/chrome/content/zotero/fileProgress.xul b/chrome/content/zotero/fileProgress.xul
deleted file mode 100644
index ed2e0160a8..0000000000
--- a/chrome/content/zotero/fileProgress.xul
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/chrome/content/zotero/overlay.js b/chrome/content/zotero/overlay.js
index ee891ee31d..6b7caea20e 100644
--- a/chrome/content/zotero/overlay.js
+++ b/chrome/content/zotero/overlay.js
@@ -27,6 +27,7 @@ var ZoteroPane = new function()
{
this.collectionsView = false;
this.itemsView = false;
+ this.__defineGetter__('loaded', function () _loaded);
//Privileged methods
this.onLoad = onLoad;
@@ -85,6 +86,7 @@ var ZoteroPane = new function()
const COLLECTIONS_HEIGHT = 32; // minimum height of the collections pane and toolbar
var self = this;
+ var _loaded = false;
var titlebarcolorState, toolbarCollapseState, titleState;
// Also needs to be changed in collectionTreeView.js
@@ -99,6 +101,11 @@ var ZoteroPane = new function()
return;
}
+ if (Zotero.locked) {
+ return;
+ }
+ _loaded = true;
+
if(Zotero.Prefs.get("zoteroPaneOnTop"))
{
var oldPane = document.getElementById('zotero-pane');
@@ -245,7 +252,7 @@ var ZoteroPane = new function()
*/
function onUnload()
{
- if (!Zotero || !Zotero.initialized) {
+ if (!Zotero || !Zotero.initialized || !_loaded) {
return;
}
@@ -262,7 +269,19 @@ var ZoteroPane = new function()
*/
function toggleDisplay()
{
- var zoteroPane = document.getElementById('zotero-pane');
+ if (!ZoteroPane.loaded) {
+ if (Zotero.locked) {
+ var pr = Components.classes["@mozilla.org/network/default-prompt;1"]
+ .getService(Components.interfaces.nsIPrompt);
+ // TODO: localize
+ var msg = "Another Zotero operation is currently in progress.\n\nPlease wait until it has finished.";
+ pr.alert("", msg);
+ return;
+ }
+ ZoteroPane.onLoad();
+ }
+
+ var zoteroPane = document.getElementById('zotero-pane-stack');
var zoteroSplitter = document.getElementById('zotero-splitter')
if (zoteroPane.getAttribute('hidden') == 'true') {
@@ -383,7 +402,7 @@ var ZoteroPane = new function()
function isShowing() {
- var zoteroPane = document.getElementById('zotero-pane');
+ var zoteroPane = document.getElementById('zotero-pane-stack');
return zoteroPane.getAttribute('hidden') != 'true' &&
zoteroPane.getAttribute('collapsed') != 'true';
}
@@ -391,21 +410,21 @@ var ZoteroPane = new function()
function fullScreen(set)
{
- var zPane = document.getElementById('zotero-pane');
+ var zoteroPane = document.getElementById('zotero-pane-stack');
if (set != undefined) {
var makeFullScreen = !!set;
}
else {
- var makeFullScreen = zPane.getAttribute('fullscreenmode') != 'true';
+ var makeFullScreen = zoteroPane.getAttribute('fullscreenmode') != 'true';
}
// Turn Z-pane flex on to stretch to window in full-screen, but off otherwise so persist works
- zPane.setAttribute('flex', makeFullScreen ? "1" : "0");
+ zoteroPane.setAttribute('flex', makeFullScreen ? "1" : "0");
document.getElementById('content').setAttribute('collapsed', makeFullScreen);
document.getElementById('zotero-splitter').setAttribute('hidden', makeFullScreen);
- zPane.setAttribute('fullscreenmode', makeFullScreen);
+ zoteroPane.setAttribute('fullscreenmode', makeFullScreen);
_setFullWindowMode(makeFullScreen);
}
@@ -468,6 +487,11 @@ var ZoteroPane = new function()
Zotero.debug(e);
}
+ if (Zotero.locked) {
+ event.preventDefault();
+ return;
+ }
+
if (from == 'zotero-pane') {
// Highlight collections containing selected items
//
@@ -497,7 +521,7 @@ var ZoteroPane = new function()
}
// Ignore keystrokes if Zotero pane is closed
- var zoteroPane = document.getElementById('zotero-pane');
+ var zoteroPane = document.getElementById('zotero-pane-stack');
if (zoteroPane.getAttribute('hidden') == 'true' ||
zoteroPane.getAttribute('collapsed') == 'true') {
return;
@@ -783,7 +807,6 @@ var ZoteroPane = new function()
function toggleTagSelector(){
- var zoteroPane = document.getElementById('zotero-pane');
var tagSelector = document.getElementById('zotero-tag-selector');
var showing = tagSelector.getAttribute('collapsed') == 'true';
@@ -805,7 +828,7 @@ var ZoteroPane = new function()
function updateTagSelectorSize() {
//Zotero.debug('Updating tag selector size');
- var zoteroPane = document.getElementById('zotero-pane');
+ var zoteroPane = document.getElementById('zotero-pane-stack');
var splitter = document.getElementById('zotero-tags-splitter');
var tagSelector = document.getElementById('zotero-tag-selector');
@@ -966,7 +989,6 @@ var ZoteroPane = new function()
}
-
this.showDuplicates = function () {
if (this.collectionsView.selection.count == 1 && this.collectionsView.selection.currentIndex != -1) {
var itemGroup = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
@@ -2225,8 +2247,11 @@ var ZoteroPane = new function()
}
}
- var separator = document.getElementById("zotero-context-separator");
- separator.hidden = !showing;
+ // If Zotero is locked, disable menu items
+ var menu = document.getElementById('zotero-content-area-context-menu');
+ for each(var menuitem in menu.firstChild.childNodes) {
+ menuitem.disabled = Zotero.locked;
+ }
}
diff --git a/chrome/content/zotero/overlay.xul b/chrome/content/zotero/overlay.xul
index 2bbbdd88a8..7a7ce39ea0 100644
--- a/chrome/content/zotero/overlay.xul
+++ b/chrome/content/zotero/overlay.xul
@@ -53,20 +53,23 @@
@@ -74,7 +77,15 @@
-
+
+
+
+
+
+
+
@@ -402,6 +413,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js
index 9f8595baf2..bff5e61452 100644
--- a/chrome/content/zotero/xpcom/db.js
+++ b/chrome/content/zotero/xpcom/db.js
@@ -217,6 +217,11 @@ Zotero.DBConnection.prototype.columnQuery = function (sql,params) {
* [1,"hello",3] or [{'int':2},{'string':'foobar'}]
*/
Zotero.DBConnection.prototype.getStatement = function (sql, params, checkParams) {
+ // TODO: limit to Zotero.DB, not all Zotero.DBConnections?
+ if (Zotero.waiting) {
+ throw ("Cannot access database layer during active Zotero.wait()");
+ }
+
var db = this._getDBConnection();
// First, determine the type of query using first word
@@ -414,6 +419,11 @@ Zotero.DBConnection.prototype.getLastErrorString = function () {
Zotero.DBConnection.prototype.beginTransaction = function () {
+ // TODO: limit to Zotero.DB, not all Zotero.DBConnections?
+ if (Zotero.waiting) {
+ throw ("Cannot access database layer during active Zotero.wait()");
+ }
+
var db = this._getDBConnection();
if (db.transactionInProgress) {
@@ -792,6 +802,11 @@ Zotero.DBConnection.prototype.backupDatabase = function (suffix) {
}
}
+ if (Zotero.locked) {
+ this._debug("Zotero is locked -- skipping backup of DB '" + this._dbName + "'", 2);
+ return false;
+ }
+
if (this.transactionInProgress()) {
this._debug("Transaction in progress--skipping backup of DB '" + this._dbName + "'", 2);
return false;
diff --git a/chrome/content/zotero/xpcom/ingester.js b/chrome/content/zotero/xpcom/ingester.js
index 49f5b18cd2..093222b8d7 100644
--- a/chrome/content/zotero/xpcom/ingester.js
+++ b/chrome/content/zotero/xpcom/ingester.js
@@ -22,14 +22,24 @@
Zotero.Ingester = new function() {
this.importHandler = function(string, uri) {
+ var frontWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
+ getService(Components.interfaces.nsIWindowWatcher).activeWindow;
+
+ if (Zotero.locked) {
+ frontWindow.Zotero_Browser.progress.changeHeadline(Zotero.getString("ingester.scrapeError"));
+ // TODO: localize
+ var desc = "A Zotero operation is currently in progress. Please wait until it finishes and try again.";
+ frontWindow.Zotero_Browser.progress.addDescription(desc);
+ frontWindow.Zotero_Browser.progress.show();
+ frontWindow.Zotero_Browser.progress.startCloseTimer(8000);
+ return;
+ }
+
// attempt to import through Zotero.Translate
var translation = new Zotero.Translate("import");
translation.setLocation(uri);
translation.setString(string);
- var frontWindow = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
- getService(Components.interfaces.nsIWindowWatcher).activeWindow;
-
frontWindow.Zotero_Browser.progress.show();
var libraryID = null;
var collection = null;
diff --git a/chrome/content/zotero/xpcom/schema.js b/chrome/content/zotero/xpcom/schema.js
index 02382527c7..50eae76a45 100644
--- a/chrome/content/zotero/xpcom/schema.js
+++ b/chrome/content/zotero/xpcom/schema.js
@@ -544,6 +544,12 @@ Zotero.Schema = new function(){
}
}
+ if (Zotero.locked) {
+ Zotero.debug('Zotero is locked -- delaying repository check', 4);
+ _setRepositoryTimer(600);
+ return false;
+ }
+
// If transaction already in progress, delay by ten minutes
if (Zotero.DB.transactionInProgress()){
Zotero.debug('Transaction in progress -- delaying repository check', 4)
diff --git a/chrome/content/zotero/xpcom/sync.js b/chrome/content/zotero/xpcom/sync.js
index e95c60ef96..56fbab035b 100644
--- a/chrome/content/zotero/xpcom/sync.js
+++ b/chrome/content/zotero/xpcom/sync.js
@@ -550,6 +550,11 @@ Zotero.Sync.Runner = new function () {
return;
}
+ if (Zotero.locked) {
+ Zotero.debug('Zotero is locked -- skipping auto-sync', 4);
+ return;
+ }
+
if (Zotero.Sync.Storage.syncInProgress) {
Zotero.debug('Storage sync already in progress -- skipping auto-sync', 4);
return;
diff --git a/chrome/content/zotero/xpcom/translate.js b/chrome/content/zotero/xpcom/translate.js
index b2f8392d76..531a5a4e98 100644
--- a/chrome/content/zotero/xpcom/translate.js
+++ b/chrome/content/zotero/xpcom/translate.js
@@ -1680,6 +1680,9 @@ Zotero.Translate.prototype._itemDone = function(item, attachedTo) {
}
delete item;
+
+ // Allow progress meter to update
+ Zotero.wait(50);
}
/*
diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js
index fbadd7c0c7..3b8fcd89e1 100644
--- a/chrome/content/zotero/xpcom/zotero.js
+++ b/chrome/content/zotero/xpcom/zotero.js
@@ -119,6 +119,18 @@ var Zotero = new function(){
return key;
};
+ /**
+ * @property {Boolean} waiting Whether Zotero is waiting for other
+ * main thread events to be processed
+ */
+ this.__defineGetter__('waiting', function () _waiting);
+
+ /**
+ * @property {Boolean} locked Whether all Zotero panes are locked
+ * with an overlay
+ */
+ this.__defineGetter__('locked', function () _locked);
+
var _startupError;
var _startupErrorHandler;
@@ -129,6 +141,8 @@ var Zotero = new function(){
var _debugLastTime;
var _localizedStringBundle;
var _localUserKey;
+ var _waiting;
+ var _locked;
/*
* Initialize the extension
@@ -380,6 +394,10 @@ var Zotero = new function(){
* Check if a DB transaction is open and, if so, disable Zotero
*/
function stateCheck() {
+ if (Zotero.locked) {
+ return true;
+ }
+
if (Zotero.DB.transactionInProgress()) {
this.initialized = false;
this.skipLoading = true;
@@ -1033,6 +1051,117 @@ var Zotero = new function(){
}
+ /**
+ * Sleep for a given amount of time, allowing other events on main thread to be processed
+ *
+ * @param {Integer} wait Milliseconds to wait
+ */
+ this.sleep = function (ms) {
+ var tm = Components.classes["@mozilla.org/thread-manager;1"].getService();
+ var endTime = Date.now() + ms;
+ var mainThread = tm.mainThread;
+ do {
+ mainThread.processNextEvent(false);
+ } while (Date.now() < endTime);
+
+ return;
+ };
+
+
+ /**
+ * Allow other events (e.g., UI updates) on main thread to be processed if necessary
+ *
+ * @param {Integer} timeout Maximum number of milliseconds to wait
+ */
+ this.wait = function (timeout) {
+ var tm = Components.classes["@mozilla.org/thread-manager;1"].getService();
+ var endTime = Date.now() + timeout;
+ var mainThread = tm.mainThread;
+ var cycles = 0;
+
+ _waiting = true;
+
+ do {
+ mainThread.processNextEvent(false);
+ cycles++;
+ } while (mainThread.hasPendingEvents() && Date.now() < endTime);
+
+ _waiting = false;
+
+ //Zotero.debug("Waited " + cycles + " cycles");
+ return cycles;
+ };
+
+
+ /**
+ * Show Zotero pane overlay and progress bar in all windows
+ *
+ * @param {String} msg
+ * @param {Boolean} [determinate=false]
+ * @return {Element[]} Array of XUL elements
+ */
+ this.showZoteroPaneProgressBar = function (msg, determinate) {
+ 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();
+
+ win.document.getElementById('zotero-pane-progress-label').value = msg;
+ var progressMeter = win.document.getElementById('zotero-pane-progressmeter')
+ if (determinate) {
+ progressMeter.mode = 'determined';
+ progressMeter.value = 0;
+ progressMeter.max = 100;
+ }
+ else {
+ progressMeter.mode = 'undetermined';
+ }
+
+ _showWindowZoteroPaneOverlay(win);
+ win.document.getElementById('zotero-pane-overlay-deck').selectedIndex = 0;
+
+ progressMeters.push(progressMeter);
+ }
+ _locked = true;
+ return progressMeters;
+ }
+
+
+ /**
+ * Hide Zotero pane overlay in all windows
+ */
+ this.hideZoteroPaneOverlay = function () {
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ var enumerator = wm.getEnumerator("navigator:browser");
+ while (enumerator.hasMoreElements()) {
+ var win = enumerator.getNext();
+ _hideWindowZoteroPaneOverlay(win);
+ }
+ _locked = false;
+ }
+
+
+ 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 _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;
+ }
+
+
/*
* Clear entries that no longer exist from various tables
*/
diff --git a/chrome/skin/default/zotero/overlay.css b/chrome/skin/default/zotero/overlay.css
index 881c7fe640..982cba08bc 100644
--- a/chrome/skin/default/zotero/overlay.css
+++ b/chrome/skin/default/zotero/overlay.css
@@ -24,13 +24,13 @@
overflow: hidden;
}
-/* these are hacks do display a window separator in full screen mode on OS X */
-window #zotero-pane[fullscreenmode="true"][platform="mac"]
+/* these are hacks to display a window separator in full screen mode on OS X */
+window #zotero-pane-stack[fullscreenmode="true"][platform="mac"]
{
border-top: 1px solid #A3A3A3;
}
-window[active="true"] #zotero-pane[fullscreenmode="true"][platform="mac"]
+window[active="true"] #zotero-pane-stack[fullscreenmode="true"][platform="mac"]
{
border-top: 1px solid black;
}
@@ -266,7 +266,7 @@ window[active="true"] #zotero-pane[fullscreenmode="true"][platform="mac"]
list-style-image: url('chrome://zotero/skin/toolbar-fullscreen-top.png');
}
-#zotero-pane[fullscreenmode="true"] #zotero-tb-fullscreen
+#zotero-pane-stack[fullscreenmode="true"] #zotero-tb-fullscreen
{
background: #666666;
-moz-border-radius: 6px;