zotero/chrome/content/zotero/preferences/preferences_advanced.js

990 lines
30 KiB
JavaScript
Raw Normal View History

/*
***** BEGIN LICENSE BLOCK *****
Copyright © 20062013 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
Components.utils.import("resource://gre/modules/Services.jsm");
import FilePicker from 'zotero/modules/filePicker';
Zotero_Preferences.Advanced = {
DEFAULT_OPENURL_RESOLVER: 'https://www.worldcat.org/registry/gateway',
_openURLResolvers: null,
init: function () {
Zotero_Preferences.Keys.init();
// Show Memory Info button
if (Zotero.Prefs.get('debug.memoryInfo')) {
document.getElementById('memory-info').hidden = false;
}
// This might not work for checkboxes if we later need to create them
// with html
var inputs = document.querySelectorAll('input[data-preference]');
for (let input of inputs) {
let preferenceName = input.dataset.preference;
input.addEventListener('change', function () {
let value = input.value;
Zotero.Prefs.set(preferenceName, value);
});
input.value = Zotero.Prefs.get(preferenceName);
}
// Set OpenURL resolver drop-down to last-known name
if (Zotero.Prefs.get('openURL.resolver')) {
let name = Zotero.Prefs.get('openURL.name');
if (name) {
document.getElementById('openurl-primary-popup').firstChild.setAttribute('label', name);
}
}
this.onDataDirLoad();
this.refreshLocale();
},
updateTranslators: Zotero.Promise.coroutine(function* () {
var updated = yield Zotero.Schema.updateFromRepository(Zotero.Schema.REPO_UPDATE_MANUAL);
var button = document.getElementById('updateButton');
if (button) {
if (updated===-1) {
var label = Zotero.getString('zotero.preferences.update.upToDate');
}
else if (updated) {
var label = Zotero.getString('zotero.preferences.update.updated');
}
else {
var label = Zotero.getString('zotero.preferences.update.error');
}
button.setAttribute('label', label);
if (updated && Zotero_Preferences.Cite) {
yield Zotero_Preferences.Cite.refreshStylesList();
}
}
}),
migrateDataDirectory: Zotero.Promise.coroutine(function* () {
var currentDir = Zotero.DataDirectory.dir;
var defaultDir = Zotero.DataDirectory.defaultDir;
if (currentDir == defaultDir) {
Zotero.debug("Already using default directory");
return;
}
Components.utils.import("resource://zotero/config.js")
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
// If there's a migration marker, point data directory back to the current location and remove
// it to trigger the migration again
var marker = OS.Path.join(defaultDir, Zotero.DataDirectory.MIGRATION_MARKER);
if (yield OS.File.exists(marker)) {
Zotero.Prefs.clear('dataDir');
Zotero.Prefs.clear('useDataDir');
yield OS.File.remove(marker);
try {
yield OS.File.remove(OS.Path.join(defaultDir, '.DS_Store'));
}
catch (e) {}
}
// ~/Zotero exists and is non-empty
if ((yield OS.File.exists(defaultDir)) && !(yield Zotero.File.directoryIsEmpty(defaultDir))) {
let buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
let index = ps.confirmEx(
window,
Zotero.getString('general.error'),
Zotero.getString('zotero.preferences.advanced.migrateDataDir.directoryExists1', defaultDir)
+ "\n\n"
+ Zotero.getString('zotero.preferences.advanced.migrateDataDir.directoryExists2'),
buttonFlags,
Zotero.getString('general.showDirectory'),
null, null, null, {}
);
if (index == 0) {
yield Zotero.File.reveal(
// Windows opens the directory, which might be confusing here, so open parent instead
Zotero.isWin ? OS.Path.dirname(defaultDir) : defaultDir
);
}
return;
}
var additionalText = '';
if (Zotero.isWin) {
try {
let numItems = yield Zotero.DB.valueQueryAsync(
"SELECT COUNT(*) FROM itemAttachments WHERE linkMode IN (?, ?)",
[Zotero.Attachments.LINK_MODE_IMPORTED_FILE, Zotero.Attachments.LINK_MODE_IMPORTED_URL]
);
if (numItems > 100) {
additionalText = '\n\n' + Zotero.getString(
'zotero.preferences.advanced.migrateDataDir.manualMigration',
[Zotero.appName, defaultDir, ZOTERO_CONFIG.CLIENT_NAME]
);
}
}
catch (e) {
Zotero.logError(e);
}
}
// Prompt to restart
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(window,
Zotero.getString('zotero.preferences.advanced.migrateDataDir.title'),
Zotero.getString(
'zotero.preferences.advanced.migrateDataDir.directoryWillBeMoved',
[ZOTERO_CONFIG.CLIENT_NAME, defaultDir]
) + '\n\n'
+ Zotero.getString(
'zotero.preferences.advanced.migrateDataDir.appMustBeRestarted', Zotero.appName
) + additionalText,
buttonFlags,
Zotero.getString('general.continue'),
null, null, null, {}
);
if (index == 0) {
yield Zotero.DataDirectory.markForMigration(currentDir);
Zotero.Utilities.Internal.quitZotero(true);
}
}),
runIntegrityCheck: async function (button) {
button.disabled = true;
try {
let ps = Services.prompt;
var ok = await Zotero.DB.integrityCheck();
if (ok) {
ok = await Zotero.Schema.integrityCheck();
if (!ok) {
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(window,
Zotero.getString('general.failed'),
Zotero.getString('db.integrityCheck.failed') + "\n\n" +
Zotero.getString('db.integrityCheck.repairAttempt') + " " +
Zotero.getString('db.integrityCheck.appRestartNeeded', Zotero.appName),
buttonFlags,
Zotero.getString('db.integrityCheck.fixAndRestart', Zotero.appName),
null, null, null, {}
);
if (index == 0) {
// Safety first
await Zotero.DB.backupDatabase();
// Fix the errors
await Zotero.Schema.integrityCheck(true);
// And run the check again
ok = await Zotero.Schema.integrityCheck();
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING);
if (ok) {
var str = 'success';
var msg = Zotero.getString('db.integrityCheck.errorsFixed');
}
else {
var str = 'failed';
var msg = Zotero.getString('db.integrityCheck.errorsNotFixed')
+ "\n\n" + Zotero.getString('db.integrityCheck.reportInForums');
}
ps.confirmEx(window,
Zotero.getString('general.' + str),
msg,
buttonFlags,
Zotero.getString('general.restartApp', Zotero.appName),
null, null, null, {}
);
var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]
.getService(Components.interfaces.nsIAppStartup);
appStartup.quit(Components.interfaces.nsIAppStartup.eAttemptQuit
| Components.interfaces.nsIAppStartup.eRestart);
}
return;
}
try {
await Zotero.DB.vacuum();
}
catch (e) {
Zotero.logError(e);
ok = false;
}
}
var str = ok ? 'passed' : 'failed';
ps.alert(window,
Zotero.getString('general.' + str),
Zotero.getString('db.integrityCheck.' + str)
+ (!ok ? "\n\n" + Zotero.getString('db.integrityCheck.dbRepairTool') : ''));
}
finally {
button.disabled = false;
}
},
resetTranslatorsAndStyles: function () {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(null,
Zotero.getString('general.warning'),
Zotero.getString('zotero.preferences.advanced.resetTranslatorsAndStyles.changesLost'),
buttonFlags,
Zotero.getString('zotero.preferences.advanced.resetTranslatorsAndStyles'),
null, null, null, {});
if (index == 0) {
Zotero.Schema.resetTranslatorsAndStyles()
.then(function () {
if (Zotero_Preferences.Export) {
Zotero_Preferences.Export.populateQuickCopyList();
}
});
}
},
resetTranslators: async function () {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(null,
Zotero.getString('general.warning'),
Zotero.getString('zotero.preferences.advanced.resetTranslators.changesLost'),
buttonFlags,
Zotero.getString('zotero.preferences.advanced.resetTranslators'),
null, null, null, {});
if (index == 0) {
let button = document.getElementById('reset-translators-button');
button.disabled = true;
try {
await Zotero.Schema.resetTranslators();
if (Zotero_Preferences.Export) {
Zotero_Preferences.Export.populateQuickCopyList();
}
}
finally {
button.disabled = false;
}
}
},
resetStyles: async function () {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(null,
Zotero.getString('general.warning'),
Zotero.getString('zotero.preferences.advanced.resetStyles.changesLost'),
buttonFlags,
Zotero.getString('zotero.preferences.advanced.resetStyles'),
null, null, null, {});
if (index == 0) {
let button = document.getElementById('reset-styles-button');
button.disabled = true;
try {
await Zotero.Schema.resetStyles()
if (Zotero_Preferences.Export) {
Zotero_Preferences.Export.populateQuickCopyList();
}
}
finally {
button.disabled = false;
}
}
},
onDataDirLoad: function () {
var useDataDir = Zotero.Prefs.get('useDataDir');
var dataDir = Zotero.Prefs.get('lastDataDir') || Zotero.Prefs.get('dataDir');
var currentDir = Zotero.DataDirectory.dir;
var defaultDataDir = Zotero.DataDirectory.defaultDir;
if (Zotero.forceDataDir) {
document.getElementById('command-line-data-dir-path').textContent = currentDir;
document.getElementById('command-line-data-dir').hidden = false;
document.getElementById('data-dir').hidden = true;
}
// Change "Use profile directory" label to home directory location unless using profile dir
if (useDataDir || currentDir == defaultDataDir) {
document.getElementById('default-data-dir').setAttribute(
'label', Zotero.getString('dataDir.default', Zotero.DataDirectory.defaultDir)
);
}
// Don't show custom data dir as in-use if set to the default
if (dataDir == defaultDataDir) {
useDataDir = false;
}
document.getElementById('data-dir-path').setAttribute('disabled', !useDataDir);
document.getElementById('migrate-data-dir').setAttribute(
'hidden', !Zotero.DataDirectory.canMigrate()
);
return useDataDir;
},
onDataDirUpdate: Zotero.Promise.coroutine(function* (event, forceNew) {
var radiogroup = document.getElementById('data-dir');
var newUseDataDir = radiogroup.selectedIndex == 1;
if (!forceNew && newUseDataDir && !this._usingDefaultDataDir()) {
return;
}
// This call shows a filepicker if needed, forces a restart if required, and does nothing if
// cancel was pressed or value hasn't changed
yield Zotero.DataDirectory.choose(
true,
!newUseDataDir,
2020-05-15 23:24:45 +00:00
() => Zotero_Preferences.openURL('https://www.zotero.org/support/zotero_data')
);
radiogroup.selectedIndex = this._usingDefaultDataDir() ? 0 : 1;
}),
chooseDataDir: function(event) {
document.getElementById('data-dir').selectedIndex = 1;
this.onDataDirUpdate(event, true);
},
getDataDirPath: function () {
// TEMP: lastDataDir can be removed once old persistent descriptors have been
// converted, which they are in getZoteroDirectory() in 5.0
var prefValue = Zotero.Prefs.get('lastDataDir') || Zotero.Prefs.get('dataDir');
// Don't show path if the default
if (prefValue == Zotero.DataDirectory.defaultDir) {
return '';
}
return prefValue || '';
},
_usingDefaultDataDir: function () {
// Legacy profile directory location
if (!Zotero.Prefs.get('useDataDir')) {
return true;
}
var dataDir = Zotero.Prefs.get('lastDataDir') || Zotero.Prefs.get('dataDir');
// Default home directory location
if (dataDir == Zotero.DataDirectory.defaultDir) {
return true;
}
return false;
},
handleOpenURLPopupShowing: async function (event) {
if (event.target.id != 'openurl-primary-popup') {
return;
}
if (!this._openURLResolvers) {
let menupopup = document.getElementById('openurl-primary-popup');
menupopup.firstChild.setAttribute('label', Zotero.getString('general.loading'));
try {
this._openURLResolvers = await Zotero.Utilities.Internal.OpenURL.getResolvers();
}
catch (e) {
Zotero.logError(e);
menupopup.firstChild.setAttribute('label', "Error loading resolvers");
return;
}
}
this.updateOpenURLResolversMenu();
},
updateOpenURLResolversMenu: function () {
if (!this._openURLResolvers) {
Zotero.debug("Resolvers not loaded -- not updating menu");
return;
}
var currentResolver = Zotero.Prefs.get('openURL.resolver');
var openURLMenu = document.getElementById('openurl-menu');
var menupopup = openURLMenu.firstChild;
menupopup.innerHTML = '';
var defaultMenuItem = document.createElement('menuitem');
defaultMenuItem.setAttribute('label', Zotero.getString('general.default'));
defaultMenuItem.setAttribute('value', this.DEFAULT_OPENURL_RESOLVER);
defaultMenuItem.setAttribute('type', 'checkbox');
menupopup.appendChild(defaultMenuItem);
var customMenuItem = document.createElement('menuitem');
customMenuItem.setAttribute('label', Zotero.getString('general.custom'));
customMenuItem.setAttribute('value', 'custom');
customMenuItem.setAttribute('type', 'checkbox');
menupopup.appendChild(customMenuItem);
menupopup.appendChild(document.createElement('menuseparator'));
var selectedName;
var lastContinent;
var lastCountry;
var currentContinentPopup;
var currentMenuPopup;
2016-05-03 21:51:12 +00:00
for (let r of this._openURLResolvers) {
// Create submenus for continents
if (r.continent != lastContinent) {
let menu = document.createElement('menu');
menu.setAttribute('label', r.continent);
openURLMenu.firstChild.appendChild(menu);
currentContinentPopup = currentMenuPopup = document.createElement('menupopup');
menu.appendChild(currentContinentPopup);
lastContinent = r.continent;
}
if (r.country != lastCountry) {
// If there's a country, create a submenu for it
if (r.country) {
let menu = document.createElement('menu');
menu.setAttribute('label', r.country);
currentContinentPopup.appendChild(menu);
let menupopup = document.createElement('menupopup');
menu.appendChild(menupopup);
currentMenuPopup = menupopup;
}
// Otherwise use the continent popup
else {
currentMenuPopup = currentContinentPopup;
}
lastCountry = r.country;
}
let menuitem = document.createElement('menuitem');
menuitem.setAttribute('label', r.name);
menuitem.setAttribute('value', r.url);
menuitem.setAttribute('type', 'checkbox');
currentMenuPopup.appendChild(menuitem);
var checked = r.url == Zotero.Prefs.get('openURL.resolver');
menuitem.setAttribute('checked', checked);
if (checked) {
selectedName = r.name;
}
}
// Default
if (currentResolver == this.DEFAULT_OPENURL_RESOLVER) {
openURLMenu.setAttribute('label', Zotero.getString('general.default'));
defaultMenuItem.setAttribute('checked', true);
Zotero.Prefs.clear('openURL.name');
}
else if (selectedName) {
openURLMenu.setAttribute('label', selectedName);
// If we found a match, update stored name
Zotero.Prefs.set('openURL.name', selectedName);
}
// Custom
else {
openURLMenu.setAttribute('label', Zotero.getString('general.custom'));
customMenuItem.setAttribute('checked', true);
Zotero.Prefs.clear('openURL.name');
}
},
handleOpenURLSelected: function (event) {
event.stopPropagation();
event.preventDefault();
if (event.target.localName != 'menuitem') {
Zotero.debug("Ignoring click on " + event.target.localName);
return;
}
var openURLMenu = document.getElementById('openurl-menu');
var openURLServerField = document.getElementById('openURLServerField');
var openURLVersionMenu = document.getElementById('openURLVersionMenu');
// Default
if (event.target.value == this.DEFAULT_OPENURL_RESOLVER) {
Zotero.Prefs.clear('openURL.name');
Zotero.Prefs.clear('openURL.resolver');
Zotero.Prefs.clear('openURL.version');
openURLServerField.value = this.DEFAULT_OPENURL_RESOLVER;
}
// If "Custom" selected, clear URL field
else if (event.target.value == "custom") {
Zotero.Prefs.clear('openURL.name');
Zotero.Prefs.set('openURL.resolver', '');
Zotero.Prefs.clear('openURL.version');
openURLServerField.value = '';
openURLServerField.focus();
}
else {
Zotero.Prefs.set('openURL.name', openURLServerField.value = event.target.label);
Zotero.Prefs.set('openURL.resolver', openURLServerField.value = event.target.value);
Zotero.Prefs.set('openURL.version', openURLVersionMenu.value = "1.0");
}
openURLMenu.firstChild.hidePopup();
setTimeout(() => {
this.updateOpenURLResolversMenu();
});
},
onOpenURLCustomized: function () {
setTimeout(() => {
this.updateOpenURLResolversMenu();
});
},
_getAutomaticLocaleMenuLabel: function () {
return Zotero.getString(
'zotero.preferences.locale.automaticWithLocale',
Zotero.Locale.availableLocales[Zotero.locale] || Zotero.locale
);
},
refreshLocale: function () {
var autoLocaleName, currentValue;
// If matching OS, get the name of the current locale
if (Zotero.Prefs.get('intl.locale.requested', true) === '') {
autoLocaleName = this._getAutomaticLocaleMenuLabel();
currentValue = 'automatic';
}
// Otherwise get the name of the locale specified in the pref
else {
autoLocaleName = Zotero.getString('zotero.preferences.locale.automatic');
currentValue = Zotero.locale;
}
// Populate menu
var menu = document.getElementById('locale-menu');
var menupopup = menu.firstChild;
menupopup.textContent = '';
// Show "Automatic (English)", "Automatic (Français)", etc.
menu.appendItem(autoLocaleName, 'automatic');
menu.menupopup.appendChild(document.createElement('menuseparator'));
// Add all available locales
for (let locale in Zotero.Locale.availableLocales) {
menu.appendItem(Zotero.Locale.availableLocales[locale], locale);
}
menu.value = currentValue;
},
onLocaleChange: function () {
var requestedLocale = Services.locale.getRequestedLocale();
var menu = document.getElementById('locale-menu');
if (menu.value == 'automatic') {
// Changed if not already set to automatic (unless we have the automatic locale name,
// meaning we just switched away to the same manual locale and back to automatic)
var changed = requestedLocale && menu.label != this._getAutomaticLocaleMenuLabel();
Services.locale.setRequestedLocales(null);
}
else {
// Changed if moving to a locale other than the current one
var changed = Zotero.locale != menu.value
Services.locale.setRequestedLocales([menu.value]);
}
if (!changed) {
return;
}
var ps = Services.prompt;
var buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING;
var index = ps.confirmEx(null,
Zotero.getString('general.restartRequired'),
Zotero.getString('general.restartRequiredForChange', Zotero.appName),
buttonFlags,
Zotero.getString('general.restartNow'),
Zotero.getString('general.restartLater'),
null, null, {});
if (index == 0) {
Zotero.Utilities.Internal.quitZotero(true);
}
}
};
Zotero_Preferences.Attachment_Base_Directory = {
getPath: function () {
var oldPath = Zotero.Prefs.get('baseAttachmentPath');
if (oldPath) {
try {
return OS.Path.normalize(oldPath);
}
catch (e) {
Zotero.logError(e);
return false;
}
}
},
choosePath: async function () {
var oldPath = this.getPath();
//Prompt user to choose new base path
var fp = new FilePicker();
if (oldPath) {
fp.displayDirectory = oldPath;
}
fp.init(window, Zotero.getString('attachmentBasePath.selectDir'), fp.modeGetFolder);
fp.appendFilters(fp.filterAll);
if (await fp.show() != fp.returnOK) {
return false;
}
var newPath = fp.file;
if (oldPath && oldPath == newPath) {
Zotero.debug("Base directory hasn't changed");
return false;
}
try {
return await this.changePath(newPath);
}
catch (e) {
Zotero.logError(e);
Zotero.alert(null, Zotero.getString('general.error'), e.message);
}
},
changePath: Zotero.Promise.coroutine(function* (basePath) {
Zotero.debug(`New base directory is ${basePath}`);
if (Zotero.File.directoryContains(Zotero.DataDirectory.dir, basePath)) {
throw new Error(
Zotero.getString(
'zotero.preferences.advanced.baseDirectory.withinDataDir',
Zotero.appName
)
);
}
// Find all current attachments with relative attachment paths
var sql = "SELECT itemID FROM itemAttachments WHERE linkMode=? AND path LIKE ?";
var params = [
Zotero.Attachments.LINK_MODE_LINKED_FILE,
Zotero.Attachments.BASE_PATH_PLACEHOLDER + "%"
];
var oldRelativeAttachmentIDs = yield Zotero.DB.columnQueryAsync(sql, params);
//Find all attachments on the new base path
var sql = "SELECT itemID FROM itemAttachments WHERE linkMode=?";
var params = [Zotero.Attachments.LINK_MODE_LINKED_FILE];
var allAttachments = yield Zotero.DB.columnQueryAsync(sql, params);
var newAttachmentPaths = {};
var numNewAttachments = 0;
var numOldAttachments = 0;
for (let i=0; i<allAttachments.length; i++) {
let attachmentID = allAttachments[i];
let attachmentPath;
let relPath = false
try {
let attachment = yield Zotero.Items.getAsync(attachmentID);
// This will return FALSE for relative paths if base directory
// isn't currently set
attachmentPath = attachment.getFilePath();
// Get existing relative path
let storedPath = attachment.attachmentPath;
if (storedPath.startsWith(Zotero.Attachments.BASE_PATH_PLACEHOLDER)) {
relPath = storedPath.substr(Zotero.Attachments.BASE_PATH_PLACEHOLDER.length);
}
}
catch (e) {
// Don't deal with bad attachment paths. Just skip them.
Zotero.debug(e, 2);
continue;
}
// If a file with the same relative path exists within the new base directory,
// don't touch the attachment, since it will continue to work
if (relPath) {
if (yield OS.File.exists(OS.Path.join(basePath, relPath))) {
numNewAttachments++;
continue;
}
}
// Files within the new base directory need to be updated to use
// relative paths (or, if the new base directory is an ancestor or
// descendant of the old one, new relative paths)
if (attachmentPath && Zotero.File.directoryContains(basePath, attachmentPath)) {
Zotero.debug(`Converting ${attachmentPath} to relative path`);
newAttachmentPaths[attachmentID] = relPath ? attachmentPath : null;
numNewAttachments++;
}
// Existing relative attachments not within the new base directory
// will be converted to absolute paths
else if (relPath && this.getPath()) {
Zotero.debug(`Converting ${relPath} to absolute path`);
newAttachmentPaths[attachmentID] = attachmentPath;
numOldAttachments++;
}
else {
Zotero.debug(`${attachmentPath} is not within the base directory`);
}
}
//Confirm change of the base path
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var chooseStrPrefix = 'attachmentBasePath.chooseNewPath.';
var clearStrPrefix = 'attachmentBasePath.clearBasePath.';
var title = Zotero.getString(chooseStrPrefix + 'title');
var msg1 = Zotero.getString(chooseStrPrefix + 'message') + "\n\n", msg2 = "", msg3 = "";
switch (numNewAttachments) {
case 0:
break;
case 1:
msg2 += Zotero.getString(chooseStrPrefix + 'existingAttachments.singular') + " ";
break;
default:
msg2 += Zotero.getString(chooseStrPrefix + 'existingAttachments.plural', numNewAttachments) + " ";
}
switch (numOldAttachments) {
case 0:
break;
case 1:
msg3 += Zotero.getString(clearStrPrefix + 'existingAttachments.singular');
break;
default:
msg3 += Zotero.getString(clearStrPrefix + 'existingAttachments.plural', numOldAttachments);
}
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(
null,
title,
(msg1 + msg2 + msg3).trim(),
buttonFlags,
Zotero.getString(chooseStrPrefix + 'button'),
null,
null,
null,
{}
);
if (index == 1) {
return false;
}
// Set new base directory
Zotero.debug("Setting base directory to " + basePath);
Zotero.Prefs.set('baseAttachmentPath', basePath);
Zotero.Prefs.set('saveRelativeAttachmentPath', true);
// Resave all attachments on base path (so that their paths become relative)
// and all other relative attachments (so that their paths become absolute)
yield Zotero.Utilities.Internal.forEachChunkAsync(
Object.keys(newAttachmentPaths),
100,
function (chunk) {
return Zotero.DB.executeTransaction(function* () {
for (let id of chunk) {
let attachment = Zotero.Items.get(id);
if (newAttachmentPaths[id]) {
attachment.attachmentPath = newAttachmentPaths[id];
}
else {
attachment.attachmentPath = attachment.getFilePath();
}
yield attachment.save({
skipDateModifiedUpdate: true
});
}
})
}
);
return true;
}),
clearPath: Zotero.Promise.coroutine(function* () {
// Find all current attachments with relative paths
var sql = "SELECT itemID FROM itemAttachments WHERE linkMode=? AND path LIKE ?";
var params = [
Zotero.Attachments.LINK_MODE_LINKED_FILE,
Zotero.Attachments.BASE_PATH_PLACEHOLDER + "%"
];
var relativeAttachmentIDs = yield Zotero.DB.columnQueryAsync(sql, params);
// Prompt for confirmation
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var strPrefix = 'attachmentBasePath.clearBasePath.';
var title = Zotero.getString(strPrefix + 'title');
var msg = Zotero.getString(strPrefix + 'message');
switch (relativeAttachmentIDs.length) {
case 0:
break;
case 1:
msg += "\n\n" + Zotero.getString(strPrefix + 'existingAttachments.singular');
break;
default:
msg += "\n\n" + Zotero.getString(strPrefix + 'existingAttachments.plural',
relativeAttachmentIDs.length);
}
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(
window,
title,
msg,
buttonFlags,
Zotero.getString(strPrefix + 'button'),
null,
null,
null,
{}
);
if (index == 1) {
return false;
}
// Disable relative path saving and then resave all relative
// attachments so that their absolute paths are stored
Zotero.debug('Clearing base directory');
Zotero.Prefs.set('saveRelativeAttachmentPath', false);
yield Zotero.Utilities.Internal.forEachChunkAsync(
relativeAttachmentIDs,
100,
function (chunk) {
return Zotero.DB.executeTransaction(function* () {
for (let id of chunk) {
let attachment = yield Zotero.Items.getAsync(id);
attachment.attachmentPath = attachment.getFilePath();
yield attachment.save({
skipDateModifiedUpdate: true
});
}
}.bind(this));
}.bind(this)
);
Zotero.Prefs.set('baseAttachmentPath', '');
}),
updateUI: Zotero.Promise.coroutine(function* () {
var filefield = document.getElementById('baseAttachmentPath');
var path = Zotero.Prefs.get('baseAttachmentPath');
Components.utils.import("resource://gre/modules/osfile.jsm");
if (yield OS.File.exists(path)) {
filefield.file = Zotero.File.pathToFile(path);
filefield.label = path;
}
else {
filefield.label = '';
}
document.getElementById('resetBasePath').disabled = !path;
})
};
Zotero_Preferences.Keys = {
init: function () {
var rows = document.getElementById('zotero-prefpane-advanced-keys-tab').getElementsByTagName('row');
for (var i=0; i<rows.length; i++) {
// Display the appropriate modifier keys for the platform
let label = rows[i].firstChild.nextSibling;
if (label.className == 'modifier') {
label.value = Zotero.isMac ? Zotero.getString('general.keys.cmdShift') : Zotero.getString('general.keys.ctrlShift');
}
}
var textboxes = document.getElementById('zotero-keys-rows').getElementsByTagName('textbox');
for (let i=0; i<textboxes.length; i++) {
let textbox = textboxes[i];
textbox.value = textbox.value.toUpperCase();
// .value takes care of the initial value, and this takes care of direct pref changes
// while the window is open
textbox.setAttribute('onsyncfrompreference', 'return Zotero_Preferences.Keys.capitalizePref(this.id)');
textbox.setAttribute('oninput', 'this.value = this.value.toUpperCase()');
}
},
capitalizePref: function (id) {
var elem = document.getElementById(id);
var pref = document.getElementById(elem.getAttribute('preference'));
if (pref.value) {
return pref.value.toUpperCase();
}
}
};