Merge branch '4.0'

Conflicts:
	chrome/content/zotero/xpcom/db.js
	chrome/content/zotero/xpcom/zotero.js
	install.rdf
	update.rdf
This commit is contained in:
Dan Stillman 2013-08-08 01:06:35 -04:00
commit bfaa0f1172
137 changed files with 696 additions and 407 deletions

View file

@ -10,7 +10,7 @@
orient="vertical"
buttons="accept"
buttonlabelaccept="&zotero.about.close;"
onload="moveToAlertPosition(); sizeToContent();"
onload="moveToAlertPosition(); sizeToContent(); document.documentElement.getButton('accept').focus();"
ondialogaccept="return true;">
<script src="include.js"/>
@ -60,7 +60,7 @@
<vbox class="subcontent">
<label class="zotero-text-link" href="http://p.yusukekamiyamane.com/" value="Fugue icons (by Yusuke Kamiyamane)"/>
<label class="zotero-text-link" href="http://www.davidashen.net/rnv.html" value="RNV (CSL validation)"/>
<label class="zotero-text-link" href="http://documentup.com/kriskowal/q/" value="q (by Kristopher Michael Kowal)"/>
<label class="zotero-text-link" href="http://documentup.com/kriskowal/q/" value="Q (by Kristopher Michael Kowal)"/>
<label class="zotero-text-link" href="http://www.famfamfam.com/lab/icons/silk/" value="Silk icons (by Mark James)"/>
<label class="zotero-text-link" href="http://simile.mit.edu/timeline/" value="SIMILE Project (Timeline)"/>
<label class="zotero-text-link" href="http://www.w3.org/2005/ajar/tab" value="Tabulator (RDF parser)"/>

View file

@ -1422,13 +1422,25 @@
|| fieldName == 'creator') {
t.setAttribute('type', 'autocomplete');
t.setAttribute('autocompletesearch', 'zotero');
let params = {
fieldName: fieldName,
libraryID: this.item.libraryID
};
if (field == 'creator') {
params.fieldMode = parseInt(elem.getAttribute('fieldMode'));
params.itemID = itemID ? itemID : '';
// Include itemID and creatorTypeID so the autocomplete can
// avoid showing results for creators already set on the item
let row = Zotero.getAncestorByTagName(elem, 'row');
let creatorTypeID = parseInt(
row.getElementsByClassName('creator-type-label')[0]
.getAttribute('typeid')
);
if (itemID) {
params.itemID = itemID;
params.creatorTypeID = creatorTypeID;
}
};
t.setAttribute(
'autocompletesearchparam', JSON.stringify(params)
@ -2163,6 +2175,25 @@
</body>
</method>
<method name="_updateAutoCompleteParams">
<parameter name="row"/>
<parameter name="changedParams"/>
<body>
<![CDATA[
var textboxes = row.getElementsByTagName('textbox');
if (textboxes.length) {
var t = textboxes[0];
var params = JSON.parse(t.getAttribute('autocompletesearchparam'));
for (var param in changedParams) {
params[param] = changedParams[param];
}
t.setAttribute('autocompletesearchparam', JSON.stringify(params));
}
]]>
</body>
</method>
<!--
/*
function modifyCreatorByID(index, creatorID, creatorTypeID) {
@ -2365,15 +2396,17 @@
oncommand="var typeBox = document.popupNode.localName == 'hbox' ? document.popupNode : document.popupNode.parentNode;
var index = parseInt(typeBox.getAttribute('fieldname').split('-')[1]);
var itemBox = document.getBindingParent(this);
if (event.explicitOriginalTarget.className == 'zotero-creator-move') {
var up = event.explicitOriginalTarget.id == 'zotero-creator-move-up';
document.getBindingParent(this).moveCreator(index, up);
itemBox.moveCreator(index, up);
return;
}
var typeID = event.explicitOriginalTarget.getAttribute('typeid');
var row = typeBox.parentNode;
var fields = document.getBindingParent(this).getCreatorFields(row);
var fields = itemBox.getCreatorFields(row);
fields.creatorTypeID = typeID;
typeBox.getElementsByTagName('label')[0].setAttribute(
'value',
@ -2382,7 +2415,16 @@
) + ':'
);
typeBox.setAttribute('typeid', typeID);
document.getBindingParent(this).modifyCreator(index, fields);"/>
/* If a creator textbox is already open, we need to
change its autocomplete parameters so that it
completes on a creator with a different creator type */
var changedParams = {
creatorTypeID: typeID
};
itemBox._updateAutoCompleteParams(row, changedParams);
itemBox.modifyCreator(index, fields);"/>
<menupopup id="zotero-field-transform-menu">
<menu label="&zotero.item.textTransform;">
<menupopup>

View file

@ -88,8 +88,7 @@ function onUnload()
var NotifyCallback = {
notify: function(action, type, ids){
// DEBUG: why does this reset without checking the modified ids?
if (noteEditor.item) {
if (noteEditor.item && ids.indexOf(noteEditor.item.id) != -1) {
noteEditor.item = noteEditor.item;
// If the document title hasn't yet been set, reset undo so

View file

@ -38,7 +38,6 @@ const ZoteroStandalone = new function() {
window.close();
return;
}
_checkRoot();
ZoteroPane.init();
ZoteroPane.makeVisible();
@ -147,32 +146,6 @@ const ZoteroStandalone = new function() {
this.onUnload = function() {
ZoteroPane.destroy();
}
/**
* Warn if Zotero Standalone is running as root and clobber the cache directory
*/
function _checkRoot() {
if(!Zotero.isWin) {
var env = Components.classes["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
var user = env.get("USER") || env.get("USERNAME");
if(user === "root") {
// Zap cache files
try {
Services.dirsvc.get("ProfLD", Components.interfaces.nsIFile).remove(true);
} catch(e) {}
// Warn user never to do this again
if(Services.prompt.confirmEx(null, "", Zotero.getString("standalone.rootWarning"),
Services.prompt.BUTTON_POS_0*Services.prompt.BUTTON_TITLE_IS_STRING |
Services.prompt.BUTTON_POS_1*Services.prompt.BUTTON_TITLE_IS_STRING,
Zotero.getString("standalone.rootWarning.exit"),
Zotero.getString("standalone.rootWarning.continue"),
null, null, {}) == 0) {
goQuitApplication();
}
}
}
}
}
/** Taken from browser.js **/

View file

@ -2951,12 +2951,48 @@ Zotero.Item.prototype.getFilename = function () {
*
* This is updated only initially and on subsequent getFile() calls.
*/
Zotero.Item.prototype.__defineGetter__('fileExists', function () {
if (this._fileExists === null) {
Zotero.Item.prototype.fileExists = function (cachedOnly) {
if (!cachedOnly && this._fileExists === null) {
this.getFile();
}
return this._fileExists;
});
};
/**
* Asynchronous cached check for file existence, used for items view
*
* This is updated only initially and on subsequent getFile() calls.
*/
Zotero.Item.prototype.fileExistsAsync = function () {
var self = this;
return Q.fcall(function () {
if (self._fileExists !== null) {
return self._fileExists;
}
if (Zotero.platformMajorVersion < 23) {
return self.fileExists();
}
if (!self.isAttachment()) {
throw new Error("Zotero.Item.fileExistsAsync() can only be called on attachment items");
}
if (self.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_URL) {
throw new Error("Zotero.Item.fileExistsAsync() cannot be called on link attachments");
}
var nsIFile = self.getFile(null, true);
Components.utils.import("resource://gre/modules/osfile.jsm");
return Q(OS.File.exists(nsIFile.path))
.then(function(exists) {
self._updateAttachmentStates(exists);
return exists;
});
});
};
/*
@ -3611,16 +3647,46 @@ Zotero.Item.prototype.getBestAttachment = function() {
*
* @return {Integer} 0 (none), 1 (present), -1 (missing)
*/
Zotero.Item.prototype.getBestAttachmentState = function () {
if (this._bestAttachmentState !== null) {
Zotero.Item.prototype.getBestAttachmentState = function (cachedOnly) {
if (cachedOnly || this._bestAttachmentState !== null) {
return this._bestAttachmentState;
}
var itemID = this.getBestAttachment();
this._bestAttachmentState = itemID ? (Zotero.Items.get(itemID).fileExists ? 1 : -1) : 0;
this._bestAttachmentState = itemID
? (Zotero.Items.get(itemID).fileExists() ? 1 : -1)
: 0;
return this._bestAttachmentState;
}
/**
* Return cached state of best attachment for use in items view
*
* @return {Promise:Integer} Promise with 0 (none), 1 (present), -1 (missing)
*/
Zotero.Item.prototype.getBestAttachmentStateAsync = function () {
var self = this;
return Q.fcall(function() {
if (self._bestAttachmentState !== null) {
return self._bestAttachmentState;
}
var itemID = self.getBestAttachment();
if (itemID) {
return Zotero.Items.get(itemID).fileExistsAsync()
.then(function (exists) {
self._bestAttachmentState = exists ? 1 : -1;
});
}
else {
self._bestAttachmentState = 0;
}
})
.then(function () {
return self._bestAttachmentState;
});
}
Zotero.Item.prototype.updateBestAttachmentState = function () {
this._bestAttachmentState = null;
}

View file

@ -1025,7 +1025,7 @@ Zotero.DBConnection.prototype.checkException = function (e) {
Zotero.DBConnection.prototype.closeDatabase = function () {
if(this._connection) {
this._connection.close();
this._connection.asyncClose();
return true;
}
}

View file

@ -598,7 +598,8 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids, extraData)
// Clear item type icons
var items = Zotero.Items.get(ids);
for (let i=0; i<items.length; i++) {
delete this._itemImages[items[i].id];
let id = items[i].id;
delete this._itemImages[id];
}
this.refresh();
@ -612,7 +613,7 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids, extraData)
var items = Zotero.Items.get(ids);
for each(var item in items) {
var id = item.id;
let id = item.id;
// Make sure row map is up to date
// if we made changes in a previous loop
@ -691,8 +692,9 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids, extraData)
var isTrash = itemGroup.isTrash();
var items = Zotero.Items.get(ids);
for each(var item in items) {
let id = item.id;
// Clear item type icon
delete this._itemImages[item.id];
delete this._itemImages[id];
// If not viewing trash and all items were deleted, ignore modify
if (allDeleted && !isTrash && !item.deleted) {
@ -1062,34 +1064,53 @@ Zotero.ItemTreeView.prototype.getImageSrc = function(row, col)
if (this._itemGroup.isTrash()) return false;
var treerow = this._getItemAtRow(row);
var item = treerow.ref;
if ((!this.isContainer(row) || !this.isContainerOpen(row))
&& Zotero.Sync.Storage.getItemDownloadImageNumber(treerow.ref)) {
&& Zotero.Sync.Storage.getItemDownloadImageNumber(item)) {
return '';
}
var itemID = item.id;
if (treerow.level === 0) {
if (treerow.ref.isRegularItem()) {
switch (treerow.ref.getBestAttachmentState()) {
case 1:
return "chrome://zotero/skin/bullet_blue.png";
case -1:
return "chrome://zotero/skin/bullet_blue_empty.png";
default:
return "";
if (item.isRegularItem()) {
let state = item.getBestAttachmentState(true);
if (state !== null) {
switch (state) {
case 1:
return "chrome://zotero/skin/bullet_blue.png";
case -1:
return "chrome://zotero/skin/bullet_blue_empty.png";
default:
return "";
}
}
item.getBestAttachmentStateAsync()
// Refresh cell when promise is fulfilled
.then(function (state) {
this._treebox.invalidateCell(row, col);
}.bind(this))
.done();
}
}
if (treerow.ref.isFileAttachment()) {
if (treerow.ref.fileExists) {
return "chrome://zotero/skin/bullet_blue.png";
}
else {
return "chrome://zotero/skin/bullet_blue_empty.png";
if (item.isFileAttachment()) {
let exists = item.fileExists(true);
if (exists !== null) {
return exists
? "chrome://zotero/skin/bullet_blue.png"
: "chrome://zotero/skin/bullet_blue_empty.png";
}
item.fileExistsAsync()
// Refresh cell when promise is fulfilled
.then(function (exists) {
this._treebox.invalidateCell(row, col);
}.bind(this));
}
}
}
@ -1354,7 +1375,7 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
case 'hasAttachment':
getField = function (row) {
if (row.ref.isAttachment()) {
var state = row.ref.fileExists ? 1 : -1;
var state = row.ref.fileExists() ? 1 : -1;
}
else if (row.ref.isRegularItem()) {
var state = row.ref.getBestAttachmentState();

View file

@ -705,7 +705,7 @@ Zotero.Sync.Storage = new function () {
var memmgr = Components.classes["@mozilla.org/memory-reporter-manager;1"]
.getService(Components.interfaces.nsIMemoryReporterManager);
memmgr.init();
Zotero.debug("Memory usage: " + memmgr.resident);
//Zotero.debug("Memory usage: " + memmgr.resident);
if (libraryID !== false) {
if (itemIDs) {
@ -819,11 +819,11 @@ Zotero.Sync.Storage = new function () {
// Spin the event loop during synchronous file access
yield Q.delay(1);
Zotero.debug("Memory usage: " + memmgr.resident);
//Zotero.debug("Memory usage: " + memmgr.resident);
let row = attachmentData[item.id];
let lk = item.libraryID + "/" + item.key;
Zotero.debug("Checking attachment file for item " + lk);
//Zotero.debug("Checking attachment file for item " + lk);
var file = item.getFile(row);
if (!file) {
@ -925,7 +925,12 @@ Zotero.Sync.Storage = new function () {
Zotero.debug("No synced files have changed locally");
}
Zotero.debug("Checked " + numItems + " files in " + (new Date() - t) + "ms");
let msg = "Checked " + numItems + " files in ";
if (libraryID !== false) {
msg += "library " + libraryID + " in ";
}
msg += (new Date() - t) + "ms";
Zotero.debug(msg);
throw new Task.Result(changed);
}
@ -935,12 +940,12 @@ Zotero.Sync.Storage = new function () {
let checkItems = function () {
if (!items.length) return;
Zotero.debug("Memory usage: " + memmgr.resident);
//Zotero.debug("Memory usage: " + memmgr.resident);
let item = items.shift();
let row = attachmentData[item.id];
let lk = item.libraryKey;
Zotero.debug("Checking attachment file for item " + lk);
//Zotero.debug("Checking attachment file for item " + lk);
let nsIFile = item.getFile(row, true);
let file = null;
@ -949,10 +954,10 @@ Zotero.Sync.Storage = new function () {
file = promisedFile;
return file.stat()
.then(function (info) {
Zotero.debug("Memory usage: " + memmgr.resident);
//Zotero.debug("Memory usage: " + memmgr.resident);
var fmtime = info.lastModificationDate.getTime();
Zotero.debug("File modification time for item " + lk + " is " + fmtime);
//Zotero.debug("File modification time for item " + lk + " is " + fmtime);
if (fmtime < 1) {
Zotero.debug("File mod time " + fmtime + " is less than 1 -- interpreting as 1", 2);
@ -1038,7 +1043,7 @@ Zotero.Sync.Storage = new function () {
})
.finally(function () {
if (file) {
Zotero.debug("Closing file for item " + lk);
//Zotero.debug("Closing file for item " + lk);
file.close();
}
})
@ -1074,7 +1079,12 @@ Zotero.Sync.Storage = new function () {
Zotero.debug("No synced files have changed locally");
}
Zotero.debug("Checked " + numItems + " files in " + (new Date() - t) + "ms");
let msg = "Checked " + numItems + " files in ";
if (libraryID !== false) {
msg += "library " + libraryID + " in ";
}
msg += (new Date() - t) + "ms";
Zotero.debug(msg);
return changed;
}));

View file

@ -822,9 +822,10 @@ Zotero.Translate.ItemGetter.prototype = {
var directory = targetFile.parent;
// The only attachments that can have multiple supporting files are of mime type
// text/html (specified in Attachments.getNumFiles())
if(attachment.attachmentMIMEType == "text/html"
// The only attachments that can have multiple supporting files are imported
// attachments of mime type text/html (specified in Attachments.getNumFiles())
if(attachment.attachmentMIMEType == "text/html"
&& linkMode != Zotero.Attachments.LINK_MODE_LINKED_FILE
&& Zotero.Attachments.getNumFiles(attachment) > 1) {
// Attachment is a snapshot with supporting files. Check if any of the
// supporting files would cause a name conflict, and build a list of transfers

View file

@ -292,6 +292,9 @@ Components.utils.import("resource://gre/modules/Services.jsm");
else {
Zotero.dir = 'ltr';
}
// Make sure that Zotero Standalone is not running as root
if(Zotero.isStandalone && !Zotero.isWin) _checkRoot();
try {
var dataDir = Zotero.getZoteroDirectory();
@ -1915,6 +1918,35 @@ Components.utils.import("resource://gre/modules/Services.jsm");
return true;
}
/**
* Warn if Zotero Standalone is running as root and clobber the cache directory if it is
*/
function _checkRoot() {
var env = Components.classes["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
var user = env.get("USER") || env.get("USERNAME");
if(user === "root") {
// Show warning
if(Services.prompt.confirmEx(null, "", Zotero.getString("standalone.rootWarning"),
Services.prompt.BUTTON_POS_0*Services.prompt.BUTTON_TITLE_IS_STRING |
Services.prompt.BUTTON_POS_1*Services.prompt.BUTTON_TITLE_IS_STRING,
Zotero.getString("standalone.rootWarning.exit"),
Zotero.getString("standalone.rootWarning.continue"),
null, null, {}) == 0) {
Components.utils.import("resource://gre/modules/ctypes.jsm");
var exit = Zotero.IPC.getLibc().declare("exit", ctypes.default_abi,
ctypes.void_t, ctypes.int);
// Zap cache files
try {
Services.dirsvc.get("ProfLD", Components.interfaces.nsIFile).remove(true);
} catch(e) {}
// Exit Zotero without giving XULRunner the opportunity to figure out the
// cache is missing. Otherwise XULRunner will zap the prefs
exit(0);
}
}
}
/**
* Observer for console messages

View file

@ -664,6 +664,8 @@ var ZoteroPane = new function()
var removeTypeChangeHandler = function () {
itemBox.removeHandler('itemtypechange', handleTypeChange);
itemBox.itemTypeMenu.firstChild.removeEventListener('popuphiding', removeTypeChangeHandler);
// Focus the title field after menu closes
itemBox.focusFirstField();
};
itemBox.addHandler('itemtypechange', handleTypeChange);
itemBox.itemTypeMenu.firstChild.addEventListener('popuphiding', removeTypeChangeHandler);
@ -765,8 +767,11 @@ var ZoteroPane = new function()
//set to Info tab
document.getElementById('zotero-view-item').selectedIndex = 0;
// Update most-recently-used list for New Item menu
if (manual) {
// Focus the title field
document.getElementById('zotero-editpane-item-box').focusFirstField();
// Update most-recently-used list for New Item menu
this.addItemTypeToNewItemTypeMRU(typeID);
}