- Added UI elements for fulltext indexing, including new Search prefpane

- Added pdfinfo support to determine number of PDF pages (requires custom binary)
- Automatic downloading and installation of customized Xpdf tools from zotero.org

Other changes:

- Various API Zotero.Fulltext API changes
- Prevent buggy automatic prefpane sizing
- New 'refresh' Notifier action to just reselect the currently selected item without sending a 'modify' trigger
- Zotero.File.putContents(file, str) -- can only handle ASCII text
- Zotero.isLinux property
This commit is contained in:
Dan Stillman 2007-07-15 18:18:22 +00:00
parent f5761d507a
commit d921d8239a
19 changed files with 1466 additions and 170 deletions

View File

@ -50,6 +50,8 @@ var ZoteroPane = new function()
this.updateTagFilter = updateTagFilter; this.updateTagFilter = updateTagFilter;
this.onCollectionSelected = onCollectionSelected; this.onCollectionSelected = onCollectionSelected;
this.itemSelected = itemSelected; this.itemSelected = itemSelected;
this.updateItemIndexedState = updateItemIndexedState;
this.reindexItem = reindexItem;
this.duplicateSelectedItem = duplicateSelectedItem; this.duplicateSelectedItem = duplicateSelectedItem;
this.deleteSelectedItem = deleteSelectedItem; this.deleteSelectedItem = deleteSelectedItem;
this.deleteSelectedCollection = deleteSelectedCollection; this.deleteSelectedCollection = deleteSelectedCollection;
@ -852,6 +854,20 @@ var ZoteroPane = new function()
document.getElementById('zotero-attachment-view').setAttribute('label', str); document.getElementById('zotero-attachment-view').setAttribute('label', str);
// Display page count
var pages = Zotero.Fulltext.getPages(item.ref.getID()).total;
var pagesRow = document.getElementById('zotero-attachment-pages');
if (pages) {
var str = Zotero.getString('itemFields.pages') + ': ' + pages;
pagesRow.setAttribute('value', str);
pagesRow.setAttribute('hidden', false);
}
else {
pagesRow.setAttribute('hidden', true);
}
this.updateItemIndexedState();
var noteEditor = document.getElementById('zotero-attachment-note-editor'); var noteEditor = document.getElementById('zotero-attachment-note-editor');
noteEditor.item = null; noteEditor.item = null;
noteEditor.note = item.ref; noteEditor.note = item.ref;
@ -881,6 +897,65 @@ var ZoteroPane = new function()
} }
/*
* Update Indexed: (Yes|No|Partial) line in attachment info pane
*/
function updateItemIndexedState() {
var indexBox = document.getElementById('zotero-attachment-index-box');
var indexStatus = document.getElementById('zotero-attachment-index-status');
var reindexButton = document.getElementById('zotero-attachment-reindex');
var item = this.itemsView._getItemAtRow(this.itemsView.selection.currentIndex);
var status = Zotero.Fulltext.getIndexedState(item.ref.getID());
var str = 'fulltext.indexState.';
switch (status) {
case Zotero.Fulltext.INDEX_STATE_UNAVAILABLE:
str += 'unavailable';
break;
case Zotero.Fulltext.INDEX_STATE_UNINDEXED:
str = 'general.no';
break;
case Zotero.Fulltext.INDEX_STATE_PARTIAL:
str += 'partial';
break;
case Zotero.Fulltext.INDEX_STATE_INDEXED:
str = 'general.yes';
break;
}
str = Zotero.getString('fulltext.indexState.indexed') + ': ' +
Zotero.getString(str);
indexStatus.setAttribute('value', str);
// Reindex button tooltip (string stored in zotero.properties)
var str = Zotero.getString('pane.items.menu.reindexItem');
reindexButton.setAttribute('tooltiptext', str);
if (Zotero.Fulltext.canReindex(item.ref.getID())) {
reindexButton.setAttribute('hidden', false);
}
else {
reindexButton.setAttribute('hidden', true);
}
}
function reindexItem() {
var items = this.getSelectedItems();
if (!items) {
return false;
}
for (var i=0; i<items.length; i++) {
if (!items[i].isAttachment()) {
continue;
}
var itemID = items[i].getID();
Zotero.Fulltext.indexItems(itemID, true);
}
this.updateItemIndexedState();
}
function duplicateSelectedItem() { function duplicateSelectedItem() {
var newItemID = this.getSelectedItems()[0].clone(); var newItemID = this.getSelectedItems()[0].clone();
var newItem = Zotero.Items.get(newItemID); var newItem = Zotero.Items.get(newItemID);
@ -1280,7 +1355,9 @@ var ZoteroPane = new function()
sep3: 9, sep3: 9,
exportItems: 10, exportItems: 10,
createBib: 11, createBib: 11,
loadReport: 12 loadReport: 12,
sep4: 13,
reindexItem: 14
}; };
var menu = document.getElementById('zotero-itemmenu'); var menu = document.getElementById('zotero-itemmenu');
@ -1297,6 +1374,22 @@ var ZoteroPane = new function()
var multiple = '.multiple'; var multiple = '.multiple';
hide.push(m.showInLibrary, m.sep1, m.addNote, m.attachSnapshot, hide.push(m.showInLibrary, m.sep1, m.addNote, m.attachSnapshot,
m.attachLink, m.sep2, m.duplicateItem); m.attachLink, m.sep2, m.duplicateItem);
// If all items can be reindexed, show option
var items = this.getSelectedItems();
var canIndex = true;
for (var i=0; i<items.length; i++) {
if (!Zotero.Fulltext.canReindex()) {
canIndex = false;
break;
}
}
if (canIndex) {
show.push(m.sep4, m.reindexItem);
}
else {
hide.push(m.sep4, m.reindexItem);
}
} }
// Single item selected // Single item selected
else else
@ -1324,12 +1417,21 @@ var ZoteroPane = new function()
if (item.isAttachment()) { if (item.isAttachment()) {
hide.push(m.duplicateItem); hide.push(m.duplicateItem);
// If not linked URL, show reindex line
if (Zotero.Fulltext.canReindex(item.getID())) {
show.push(m.sep4, m.reindexItem);
}
else {
hide.push(m.sep4, m.reindexItem);
}
} }
else { else {
show.push(m.duplicateItem); show.push(m.duplicateItem);
hide.push(m.sep4, m.reindexItem);
} }
} }
} }
// No items selected
else else
{ {
// Show in Library // Show in Library
@ -1342,7 +1444,7 @@ var ZoteroPane = new function()
disable.push(m.showInLibrary, m.duplicateItem, m.deleteItem, disable.push(m.showInLibrary, m.duplicateItem, m.deleteItem,
m.deleteFromLibrary, m.exportItems, m.createBib, m.loadReport); m.deleteFromLibrary, m.exportItems, m.createBib, m.loadReport);
hide.push(m.addNote, m.attachSnapshot, m.attachLink, m.sep2); hide.push(m.addNote, m.attachSnapshot, m.attachLink, m.sep2, m.sep4, m.reindexItem);
} }
// Remove from collection // Remove from collection
@ -1361,6 +1463,7 @@ var ZoteroPane = new function()
menu.childNodes[m.exportItems].setAttribute('label', Zotero.getString('pane.items.menu.export' + multiple)); menu.childNodes[m.exportItems].setAttribute('label', Zotero.getString('pane.items.menu.export' + multiple));
menu.childNodes[m.createBib].setAttribute('label', Zotero.getString('pane.items.menu.createBib' + multiple)); menu.childNodes[m.createBib].setAttribute('label', Zotero.getString('pane.items.menu.createBib' + multiple));
menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.items.menu.generateReport' + multiple)); menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.items.menu.generateReport' + multiple));
menu.childNodes[m.reindexItem].setAttribute('label', Zotero.getString('pane.items.menu.reindexItem' + multiple));
for (var i in disable) for (var i in disable)
{ {

View File

@ -101,6 +101,8 @@
<menuitem oncommand="Zotero_File_Interface.exportItems();"/> <menuitem oncommand="Zotero_File_Interface.exportItems();"/>
<menuitem oncommand="Zotero_File_Interface.bibliographyFromItems();"/> <menuitem oncommand="Zotero_File_Interface.bibliographyFromItems();"/>
<menuitem oncommand="Zotero_Report_Interface.loadItemReport()"/> <menuitem oncommand="Zotero_Report_Interface.loadItemReport()"/>
<menuseparator/>
<menuitem oncommand="ZoteroPane.reindexItem();"/>
</popup> </popup>
</popupset> </popupset>
@ -305,10 +307,17 @@
<button id="zotero-attachment-view" flex="1" oncommand="ZoteroPane.viewSelectedAttachment(event);"/> <button id="zotero-attachment-view" flex="1" oncommand="ZoteroPane.viewSelectedAttachment(event);"/>
<button id="zotero-attachment-show" label="&zotero.item.attachment.file.show;" flex="1" oncommand="ZoteroPane.showSelectedAttachmentInFilesystem()"/> <button id="zotero-attachment-show" label="&zotero.item.attachment.file.show;" flex="1" oncommand="ZoteroPane.showSelectedAttachmentInFilesystem()"/>
</hbox> </hbox>
<vbox>
<label id="zotero-attachment-url" class="text-link" crop="end" onclick="ZoteroPane.loadURI(this.value, event)"/> <label id="zotero-attachment-url" class="text-link" crop="end" onclick="ZoteroPane.loadURI(this.value, event)"/>
<label id="zotero-attachment-accessed"/> <label id="zotero-attachment-accessed"/>
</vbox> <label id="zotero-attachment-pages"/>
<hbox id="zotero-attachment-index-box">
<label id="zotero-attachment-index-status"/>
<toolbarbutton id="zotero-attachment-reindex" oncommand="ZoteroPane.reindexItem()"/>
</hbox>
<noteeditor id="zotero-attachment-note-editor" notitle="1" flex="1"/> <noteeditor id="zotero-attachment-note-editor" notitle="1" flex="1"/>
</vbox> </vbox>
</deck> </deck>

View File

@ -33,6 +33,7 @@ function init()
populateQuickCopyList(); populateQuickCopyList();
updateQuickCopyInstructions(); updateQuickCopyInstructions();
initSearchPane();
} }
@ -261,9 +262,9 @@ function refreshQuickCopySiteList() {
treeitem.appendChild(treerow); treeitem.appendChild(treerow);
treechildren.appendChild(treeitem); treechildren.appendChild(treeitem);
} }
} }
function deleteSelectedQuickCopySite() { function deleteSelectedQuickCopySite() {
var tree = document.getElementById('quickCopy-siteSettings'); var tree = document.getElementById('quickCopy-siteSettings');
var treeitem = tree.lastChild.childNodes[tree.currentIndex]; var treeitem = tree.lastChild.childNodes[tree.currentIndex];
@ -291,6 +292,467 @@ function updateQuickCopyInstructions() {
} }
function rebuildIndexPrompt() {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
createInstance(Components.interfaces.nsIPromptService);
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_2) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(null,
Zotero.getString('zotero.preferences.search.rebuildIndex'),
Zotero.getString('zotero.preferences.search.rebuildWarning',
Zotero.getString('zotero.preferences.search.indexUnindexed')),
buttonFlags,
Zotero.getString('zotero.preferences.search.rebuildIndex'),
Zotero.getString('zotero.preferences.search.indexUnindexed'),
null, null, {});
if (index == 0) {
Zotero.Fulltext.rebuildIndex();
}
else if (index == 1) {
Zotero.Fulltext.rebuildIndex(true)
}
updateIndexStats();
}
function clearIndexPrompt() {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
createInstance(Components.interfaces.nsIPromptService);
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_2) * (ps.BUTTON_TITLE_CANCEL);
var index = ps.confirmEx(null,
Zotero.getString('zotero.preferences.search.clearIndex'),
Zotero.getString('zotero.preferences.search.clearWarning',
Zotero.getString('zotero.preferences.search.clearNonLinkedURLs')),
buttonFlags,
Zotero.getString('zotero.preferences.search.clearIndex'),
Zotero.getString('zotero.preferences.search.clearNonLinkedURLs'),
null, null, {});
if (index == 0) {
Zotero.Fulltext.clearIndex();
}
else if (index == 1) {
Zotero.Fulltext.clearIndex(true);
}
updateIndexStats();
}
function initSearchPane() {
document.getElementById('fulltext-rebuildIndex').setAttribute('label',
Zotero.getString('zotero.preferences.search.rebuildIndex'));
document.getElementById('fulltext-clearIndex').setAttribute('label',
Zotero.getString('zotero.preferences.search.clearIndex'));
updatePDFToolsStatus();
}
/*
* Update window according to installation status for PDF tools
* (e.g. status line, install/update button, etc.)
*/
function updatePDFToolsStatus() {
var converterIsRegistered = Zotero.Fulltext.pdfConverterIsRegistered();
var infoIsRegistered = Zotero.Fulltext.pdfInfoIsRegistered();
var converterStatusLabel = document.getElementById('pdfconverter-status');
var infoStatusLabel = document.getElementById('pdfinfo-status');
var requiredLabel = document.getElementById('pdftools-required');
var updateButton = document.getElementById('pdftools-update-button');
var documentationLink = document.getElementById('pdftools-documentation-link');
var settingsBox = document.getElementById('pdftools-settings');
// If we haven't already generated the required and documentation messages
if (!converterIsRegistered && !requiredLabel.hasChildNodes()) {
var utils = new Zotero.Utilities();
// Xpdf link
var str = Zotero.getString('zotero.preferences.search.pdf.toolsRequired',
[Zotero.Fulltext.pdfConverterName, Zotero.Fulltext.pdfInfoName,
'<a href="' + Zotero.Fulltext.pdfToolsURL + '">'
+ Zotero.Fulltext.pdfToolsName + '</a>']);
var parts = utils.parseMarkup(str);
for (var i=0; i<parts.length; i++) {
var part = parts[i];
if (part.type == 'text') {
var elem = document.createTextNode(part.text);
}
else if (part.type == 'link') {
var elem = document.createElement('label');
elem.setAttribute('value', part.text);
elem.setAttribute('class', 'text-link');
for (var key in part.attributes) {
elem.setAttribute(key, part.attributes[key]);
if (key == 'href') {
elem.setAttribute('tooltiptext', part.attributes[key]);
}
}
}
requiredLabel.appendChild(elem);
}
requiredLabel.appendChild(document.createTextNode(' '
+ Zotero.getString('zotero.preferences.search.pdf.automaticInstall')));
// Documentation link
var link = '<a href="http://www.zotero.org/documentation/pdf_fulltext_indexing">'
+ Zotero.getString('zotero.preferences.search.pdf.documentationLink')
+ '</a>';
var str = Zotero.getString('zotero.preferences.search.pdf.advancedUsers', link);
var parts = utils.parseMarkup(str);
for (var i=0; i<parts.length; i++) {
var part = parts[i];
if (part.type == 'text') {
var elem = document.createTextNode(part.text);
}
else if (part.type == 'link') {
var elem = document.createElement('label');
elem.setAttribute('value', part.text);
elem.setAttribute('class', 'text-link');
for (var key in part.attributes) {
elem.setAttribute(key, part.attributes[key]);
if (key == 'href') {
elem.setAttribute('tooltiptext', part.attributes[key]);
}
}
}
documentationLink.appendChild(elem);
}
}
// converter status line
var prefix = 'zotero.preferences.search.pdf.tool';
if (converterIsRegistered) {
var version = Zotero.Fulltext.pdfConverterVersion;
str = Zotero.getString(prefix + 'Registered',
Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform',
[Zotero.Fulltext.pdfConverterName, version]));
}
else {
str = Zotero.getString(prefix + 'NotRegistered',
[Zotero.Fulltext.pdfConverterFileName]);
}
converterStatusLabel.setAttribute('value', str);
// pdfinfo status line
if (infoIsRegistered) {
var version = Zotero.Fulltext.pdfInfoVersion;
str = Zotero.getString(prefix + 'Registered',
Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform',
[Zotero.Fulltext.pdfInfoName, version]));
}
else {
str = Zotero.getString(prefix + 'NotRegistered',
[Zotero.Fulltext.pdfInfoFileName]);
}
infoStatusLabel.setAttribute('value', str);
str = converterIsRegistered ?
Zotero.getString('general.checkForUpdate') :
Zotero.getString('zotero.preferences.search.pdf.checkForInstaller');
updateButton.setAttribute('label', str);
requiredLabel.setAttribute('hidden', converterIsRegistered);
documentationLink.setAttribute('hidden', converterIsRegistered);
settingsBox.setAttribute('hidden', !converterIsRegistered);
}
/*
* Check available versions of PDF tools from server and prompt for installation
* if a newer version is available
*/
function checkPDFToolsDownloadVersion() {
var url = Zotero.Fulltext.pdfToolsDownloadBaseURL
+ Zotero.platform.replace(' ', '-') + '.latest';
// Find latest version for this platform
var sent = Zotero.Utilities.HTTP.doGet(url, function (xmlhttp) {
try {
if (xmlhttp.status == 200) {
var converterIsRegistered = Zotero.Fulltext.pdfConverterIsRegistered();
var infoIsRegistered = Zotero.Fulltext.pdfInfoIsRegistered();
var bothRegistered = converterIsRegistered && infoIsRegistered;
var converterVersion = xmlhttp.responseText.split(/\s/)[0];
var infoVersion = xmlhttp.responseText.split(/\s/)[1];
var converterVersionAvailable = converterVersion &&
(!converterIsRegistered ||
Zotero.Fulltext.pdfConverterVersion == 'UNKNOWN' ||
converterVersion > Zotero.Fulltext.pdfConverterVersion);
var infoVersionAvailable = infoVersion &&
(!infoIsRegistered ||
Zotero.Fulltext.pdfInfoVersion == 'UNKNOWN' ||
infoVersion > Zotero.Fulltext.pdfInfoVersion);
var bothAvailable = converterVersionAvailable && infoVersionAvailable;
/*
Zotero.debug(converterIsRegistered);
Zotero.debug(infoIsRegistered);
Zotero.debug(converterVersion);
Zotero.debug(infoVersion);
Zotero.debug(Zotero.Fulltext.pdfConverterVersion);
Zotero.debug(Zotero.Fulltext.pdfInfoVersion);
Zotero.debug(converterVersionAvailable);
Zotero.debug(infoVersionAvailable);
*/
// Up to date -- disable update button
if (!converterVersionAvailable && !infoVersionAvailable) {
var button = document.getElementById('pdftools-update-button');
button.setAttribute('label', Zotero.getString('zotero.preferences.update.upToDate'));
button.setAttribute('disabled', true);
}
// New version available -- display update prompt
else {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
createInstance(Components.interfaces.nsIPromptService);
var buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
var msg = Zotero.getString('zotero.preferences.search.pdf.available'
+ ((converterIsRegistered || infoIsRegistered) ? 'Updates' : 'Downloads'),
[Zotero.platform, 'zotero.org']) + '\n\n';
if (converterVersionAvailable) {
tvp = Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform',
[Zotero.Fulltext.pdfConverterName, converterVersion]);
msg += '- ' + tvp + '\n';
}
if (infoVersionAvailable) {
tvp = Zotero.getString('zotero.preferences.search.pdf.toolVersionPlatform',
[Zotero.Fulltext.pdfInfoName, infoVersion]);
msg += '- ' + tvp + '\n';
}
msg += '\n';
msg += Zotero.getString('zotero.preferences.search.pdf.zoteroCanInstallVersion'
+ (bothAvailable ? 's' : ''));
var index = ps.confirmEx(null,
converterIsRegistered ?
Zotero.getString('general.updateAvailable') : '',
msg,
buttonFlags,
converterIsRegistered ?
Zotero.getString('general.upgrade') :
Zotero.getString('general.install'),
null, null, null, {});
if (index == 0) {
var installVersions = {
converter: converterVersionAvailable ?
converterVersion : null,
info: infoVersionAvailable ?
infoVersion : null
};
installPDFTools(installVersions);
}
}
}
// Version not found for platform
else if (xmlhttp.status == 404) {
onPDFToolsDownloadError(404);
}
}
catch (e) {
onPDFToolsDownloadError(e);
}
});
// Browser is offline
if (!sent) {
onPDFToolsDownloadError();
}
}
/*
* Begin installation of specified PDF tools from server -- does a HEAD call to
* make sure file exists and then calls downloadPDFTool() if so
*/
function installPDFTools(installVersions) {
if (!installVersions) {
installVersions = {
converter: true,
info: true
};
}
// We install the converter first if it's available
var url = Zotero.Fulltext.pdfToolsDownloadBaseURL;
if (installVersions.converter) {
var tool = 'converter';
var version = installVersions.converter;
url += Zotero.Fulltext.pdfConverterFileName + '-' + installVersions.converter;
}
else if (installVersions.info) {
var tool = 'info';
var version = installVersions.info;
url += Zotero.Fulltext.pdfInfoFileName + '-' + installVersions.info;
}
else {
return;
}
// Find latest version for this platform
var sent = Zotero.Utilities.HTTP.doHead(url, function (xmlhttp) {
try {
if (xmlhttp.status == 200) {
// If doing both and on converter, chain pdfinfo
if (installVersions.converter && installVersions.info) {
downloadPDFTool(tool, version, function () {
return installPDFTools({ info: installVersions.info });
});
}
else {
downloadPDFTool(tool, version);
}
}
// Version not found for platform
else if (xmlhttp.status == 404) {
onPDFToolsDownloadError(404);
}
}
catch (e) {
onPDFToolsDownloadError(e);
}
});
// Browser is offline
if (!sent) {
onPDFToolsDownloadError();
}
}
/*
* Download and install specified PDF tool
*/
function downloadPDFTool(tool, version, callback) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
if (tool == 'converter') {
var fileName = Zotero.Fulltext.pdfConverterFileName;
}
else {
var fileName = Zotero.Fulltext.pdfInfoFileName;
}
var url = Zotero.Fulltext.pdfToolsDownloadBaseURL + fileName + '-' + version;
var uri = ioService.newURI(url, null, null);
var file = Zotero.getZoteroDirectory();
file.append(fileName);
var fileURL = ioService.newFileURI(file);
const nsIWBP = Components.interfaces.nsIWebBrowserPersist;
var wbp = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(nsIWBP);
var progressListener = new Zotero.WebProgressFinishListener(function () {
// Set permissions to 755
if (Zotero.isMac) {
file.permissions = 33261;
}
else if (Zotero.isLinux) {
file.permissions = 493;
}
// Write the version number to a file
var versionFile = Zotero.getZoteroDirectory();
versionFile.append(fileName + '.version');
Zotero.File.putContents(versionFile, version + '');
Zotero.Fulltext.registerPDFTool(tool);
// Used to install info tool after converter
if (callback) {
callback();
}
// If done
else {
updatePDFToolsStatus();
}
});
/*
var tr = Components.classes["@mozilla.org/transfer;1"].
createInstance(Components.interfaces.nsITransfer);
tr.init(uri, fileURL, "", null, null, null, wbp);
*/
document.getElementById('pdftools-update-button').disabled = true;
var str = Zotero.getString('zotero.preferences.search.pdf.downloading');
document.getElementById('pdftools-update-button').setAttribute('label', str);
wbp.progressListener = progressListener;
Zotero.debug("Saving " + uri.spec + " to " + fileURL.spec);
wbp.saveURI(uri, null, null, null, null, fileURL);
}
function onPDFToolsDownloadError(e) {
if (e == 404) {
var str = Zotero.getString('zotero.preferences.search.pdf.toolDownloadsNotAvailable',
Zotero.Fulltext.pdfToolsName) + ' '
+ Zotero.getString('zotero.preferences.search.pdf.viewManualInstructions');
}
else if (e) {
Components.utils.reportError(e);
var str = Zotero.getString('zotero.preferences.search.pdf.toolsDownloadError', Zotero.Fulltext.pdfToolsName)
+ ' ' + Zotero.getString('zotero.preferences.search.pdf.tryAgainOrViewManualInstructions');
}
else {
var info = Components.classes["@mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
var browser = info.name; // Returns "Firefox" for Firefox
var str = Zotero.getString('general.browserIsOffline', browser);
}
alert(str);
}
function updateIndexStats() {
var stats = Zotero.Fulltext.getIndexStats();
document.getElementById('fulltext-stats-indexed').
lastChild.setAttribute('value', stats.indexed);
document.getElementById('fulltext-stats-partial').
lastChild.setAttribute('value', stats.partial);
document.getElementById('fulltext-stats-unindexed').
lastChild.setAttribute('value', stats.unindexed);
document.getElementById('fulltext-stats-words').
lastChild.setAttribute('value', stats.words);
}
/*
* Unused
*/
function revealDataDirectory() {
var dataDir = Zotero.getZoteroDirectory();
dataDir.QueryInterface(Components.interfaces.nsILocalFile);
try {
dataDir.reveal();
}
catch (e) {
// TODO: This won't work on Linux
}
}
function onOpenURLSelected() function onOpenURLSelected()
{ {

View File

@ -66,10 +66,10 @@ To add a new preference:
<rows> <rows>
<row> <row>
<hbox> <hbox id="position-menu-box-label">
<label value="&zotero.preferences.position;" control="positionMenu"/> <label value="&zotero.preferences.position;" control="positionMenu"/>
</hbox> </hbox>
<hbox> <hbox id="position-menu-box">
<menulist id="positionMenu" preference="pref-zoteroPaneOnTop"> <menulist id="positionMenu" preference="pref-zoteroPaneOnTop">
<menupopup> <menupopup>
<menuitem label="&zotero.preferences.position.above;" value="true"/> <menuitem label="&zotero.preferences.position.above;" value="true"/>
@ -151,6 +151,104 @@ To add a new preference:
</prefpane> </prefpane>
<prefpane id="zotero-prefpane-search" label="&zotero.preferences.prefpane.search;"
onpaneload="updateIndexStats()">
<preferences>
<preference id="pref-fulltext-textMaxLength" name="extensions.zotero.fulltext.textMaxLength" type="int"/>
<preference id="pref-fulltext-pdfmaxpages" name="extensions.zotero.fulltext.pdfMaxPages" type="int"/>
</preferences>
<groupbox>
<caption label="&zotero.preferences.search.fulltextCache;"/>
<hbox>
<button id="fulltext-rebuildIndex" flex="1" oncommand="rebuildIndexPrompt()"/>
<button id="fulltext-clearIndex" flex="1" oncommand="clearIndexPrompt()"/>
</hbox>
<grid id="fulltext-settings">
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row>
<hbox>
<label value="&zotero.preferences.fulltext.textMaxLength;"/>
</hbox>
<hbox>
<textbox size="10" preference="pref-fulltext-textMaxLength"/>
<label value="(&zotero.preferences.default; 500000)"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
<groupbox id="pdftools-box">
<caption label="&zotero.preferences.search.pdfIndexing;"/>
<label id="pdfconverter-status"/>
<label id="pdfinfo-status"/>
<label id="pdftools-required" hidden="true"/>
<hbox>
<button id="pdftools-update-button" flex="1" oncommand="checkPDFToolsDownloadVersion()"/>
</hbox>
<label id="pdftools-documentation-link" hidden="true"/>
<grid id="pdftools-settings" hidden="true">
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row>
<hbox>
<label value="&zotero.preferences.fulltext.pdfMaxPages;"/>
</hbox>
<hbox>
<textbox size="5" preference="pref-fulltext-pdfmaxpages"/>
<label value="(&zotero.preferences.default; 100)"/>
</hbox>
</row>
</rows>
</grid>
</groupbox>
<groupbox id="fulltext-stats">
<caption label="&zotero.preferences.search.indexStats;"/>
<grid>
<columns>
<column/>
<column/>
</columns>
<rows>
<row id="fulltext-stats-indexed">
<label value="Indexed:"/>
<label/>
</row>
<row id="fulltext-stats-partial">
<label value="Partial:"/>
<label/>
</row>
<row id="fulltext-stats-unindexed">
<label value="Unindexed:"/>
<label/>
</row>
<row id="fulltext-stats-words">
<label value="Words:"/>
<label/>
</row>
</rows>
</grid>
</groupbox>
</prefpane>
<prefpane id="zotero-prefpane-export" label="&zotero.preferences.prefpane.export;"> <prefpane id="zotero-prefpane-export" label="&zotero.preferences.prefpane.export;">
<preferences> <preferences>
<preference id="pref-quickCopy-setting" name="extensions.zotero.export.quickCopy.setting" type="string"/> <preference id="pref-quickCopy-setting" name="extensions.zotero.export.quickCopy.setting" type="string"/>

View File

@ -35,6 +35,7 @@ Zotero.Attachments = new function(){
this.importFromDocument = importFromDocument; this.importFromDocument = importFromDocument;
this.getFileBaseNameFromItem = getFileBaseNameFromItem; this.getFileBaseNameFromItem = getFileBaseNameFromItem;
this.createDirectoryForItem = createDirectoryForItem; this.createDirectoryForItem = createDirectoryForItem;
this.getStorageDirectory = getStorageDirectory;
this.getPath = getPath; this.getPath = getPath;
var self = this; var self = this;
@ -499,12 +500,14 @@ Zotero.Attachments = new function(){
if (mimeType == 'application/pdf') { if (mimeType == 'application/pdf') {
var f = function() { var f = function() {
Zotero.Fulltext.indexPDF(file, itemID);; Zotero.Fulltext.indexPDF(file, itemID);
Zotero.Notifier.trigger('refresh', 'item', itemID);
}; };
} }
else { else {
var f = function() { var f = function() {
Zotero.Fulltext.indexDocument(document, itemID); Zotero.Fulltext.indexDocument(document, itemID);
Zotero.Notifier.trigger('refresh', 'item', itemID);
}; };
} }
@ -780,8 +783,7 @@ Zotero.Attachments = new function(){
* Create directory for attachment files within storage directory * Create directory for attachment files within storage directory
*/ */
function createDirectoryForItem(itemID) { function createDirectoryForItem(itemID) {
var dir = Zotero.getStorageDirectory(); var dir = this.getStorageDirectory(itemID);
dir.append(itemID);
if (!dir.exists()) { if (!dir.exists()) {
dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755); dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
} }
@ -789,9 +791,16 @@ Zotero.Attachments = new function(){
} }
function getStorageDirectory(itemID) {
var dir = Zotero.getStorageDirectory();
dir.append(itemID);
return dir;
}
/* /*
* Gets a relative path for imported attachments and an absolute path * Gets a relative descriptor for imported attachments and a persistent
* for files outside the storage directory * descriptor for files outside the storage directory
*/ */
function getPath(file, linkMode) { function getPath(file, linkMode) {
if (linkMode == self.LINK_MODE_IMPORTED_URL || if (linkMode == self.LINK_MODE_IMPORTED_URL ||

View File

@ -25,6 +25,7 @@ Zotero.File = new function(){
this.getClosestDirectory = getClosestDirectory; this.getClosestDirectory = getClosestDirectory;
this.getSample = getSample; this.getSample = getSample;
this.getContents = getContents; this.getContents = getContents;
this.putContents = putContents;
this.getCharsetFromFile = getCharsetFromFile; this.getCharsetFromFile = getCharsetFromFile;
this.addCharsetListener = addCharsetListener; this.addCharsetListener = addCharsetListener;
@ -114,6 +115,23 @@ Zotero.File = new function(){
} }
/*
* Write string to a file, overwriting existing file if necessary
*
* Note: Can only handle ASCII text!
*/
function putContents(file, str) {
if (file.exists()) {
file.remove(null);
}
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
foStream.write(str, str.length);
foStream.close();
}
/* /*
* Not implemented, but it'd sure be great if it were * Not implemented, but it'd sure be great if it were
*/ */

View File

@ -25,11 +25,10 @@ Zotero.Fulltext = new function(){
const CACHE_FILE = '.zotero-ft-cache'; const CACHE_FILE = '.zotero-ft-cache';
this.init = init; this.init = init;
this.registerPDFToText = registerPDFToText; this.registerPDFTool = registerPDFTool;
this.cacheIsOutdated = cacheIsOutdated; this.pdfConverterIsRegistered = pdfConverterIsRegistered;
this.rebuildCache = rebuildCache; this.pdfInfoIsRegistered = pdfInfoIsRegistered;
this.isCachedMIMEType = isCachedMIMEType; this.isCachedMIMEType = isCachedMIMEType;
this.indexWord = indexWord;
this.indexWords = indexWords; this.indexWords = indexWords;
this.indexDocument = indexDocument; this.indexDocument = indexDocument;
this.indexString = indexString; this.indexString = indexString;
@ -39,16 +38,62 @@ Zotero.Fulltext = new function(){
this.findTextInFile = findTextInFile; this.findTextInFile = findTextInFile;
this.findTextInItems = findTextInItems; this.findTextInItems = findTextInItems;
this.clearItemWords = clearItemWords; this.clearItemWords = clearItemWords;
this.getPages = getPages;
this.getTotalPagesFromFile = getTotalPagesFromFile;
this.getChars = getChars;
this.getTotalCharsFromFile = getTotalCharsFromFile;
this.setChars = setChars;
this.setPages = setPages;
this.getIndexedState = getIndexedState;
this.getIndexStats = getIndexStats;
this.canReindex = canReindex;
this.rebuildIndex = rebuildIndex;
this.clearIndex = clearIndex;
this.clearCacheFile = clearCacheFile;
this.clearCacheFiles = clearCacheFiles;
//this.clearItemContent = clearItemContent; //this.clearItemContent = clearItemContent;
this.purgeUnusedWords = purgeUnusedWords; this.purgeUnusedWords = purgeUnusedWords;
this.HTMLToText = HTMLToText; this.HTMLToText = HTMLToText;
this.semanticSplitter = semanticSplitter; this.semanticSplitter = semanticSplitter;
var _pdftotext = null; this.__defineGetter__("pdfToolsDownloadBaseURL", function() { return 'http://www.zotero.org/download/xpdf/'; });
this.__defineGetter__("pdfToolsName", function() { return 'Xpdf'; });
this.__defineGetter__("pdfToolsURL", function() { return 'http://www.foolabs.com/xpdf/'; });
this.__defineGetter__("pdfConverterName", function() { return 'pdftotext'; });
this.__defineGetter__("pdfInfoName", function() { return 'pdfinfo'; });
this.__defineGetter__("pdfConverterCacheFile", function () { return '.zotero-ft-cache'; });
this.__defineGetter__("pdfInfoCacheFile", function () { return '.zotero-ft-info'; });
this.__defineGetter__("INDEX_STATE_UNAVAILABLE", function () { return 0; });
this.__defineGetter__("INDEX_STATE_UNINDEXED", function () { return 1; });
this.__defineGetter__("INDEX_STATE_PARTIAL", function () { return 2; });
this.__defineGetter__("INDEX_STATE_INDEXED", function () { return 3; });
var _pdfConverterVersion = null;
var _pdfConverterFileName = null;
var _pdfConverter = null; // nsIFile to executable
var _pdfInfoVersion = null;
var _pdfInfoFileName = null;
var _pdfInfo = null; // nsIFile to executable
var self = this;
function init() { function init() {
this.registerPDFToText(); var platform = Zotero.platform.replace(' ', '-');
_pdfConverterFileName = this.pdfConverterName + '-' + platform;
_pdfInfoFileName = this.pdfInfoName + '-' + platform;
if (Zotero.isWin) {
_pdfConverterFileName += '.exe';
}
this.__defineGetter__("pdfConverterFileName", function() { return _pdfConverterFileName; });
this.__defineGetter__("pdfConverterVersion", function() { return _pdfConverterVersion; });
this.__defineGetter__("pdfInfoFileName", function() { return _pdfInfoFileName; });
this.__defineGetter__("pdfInfoVersion", function() { return _pdfInfoVersion; });
this.registerPDFTool('converter');
this.registerPDFTool('info');
} }
@ -58,67 +103,89 @@ Zotero.Fulltext = new function(){
* {platform} is navigator.platform, with spaces replaced by hyphens * {platform} is navigator.platform, with spaces replaced by hyphens
* e.g. "Win32", "Linux-i686", "MacPPC", "MacIntel", etc. * e.g. "Win32", "Linux-i686", "MacPPC", "MacIntel", etc.
*/ */
function registerPDFToText() { function registerPDFTool(tool) {
var errMsg = false;
var exec = Zotero.getZoteroDirectory(); var exec = Zotero.getZoteroDirectory();
var fileName = 'pdftotext-' + Zotero.platform.replace(' ', '-'); switch (tool) {
if (Zotero.isWin) { case 'converter':
fileName += '.exe'; var toolName = this.pdfConverterName;
} var fileName = _pdfConverterFileName
break;
var errMsg = false; case 'info':
var toolName = this.pdfInfoName;
var fileName = _pdfInfoFileName
break;
default:
throw ("Invalid PDF tool type '" + tool + "' in Zotero.Fulltext.registerPDFTool()");
}
exec.append(fileName); exec.append(fileName);
if (exec.exists()) { if (exec.exists()) {
// DEBUG: I'm not sure isSymlink() actually works on any platforms
if (exec.isSymlink()) { if (exec.isSymlink()) {
exec = exec.target; exec = exec.target;
if (!exec.target) { if (!exec.target) {
errMsg = fileName + ' symlink target not found'; errMsg = fileName + ' symlink target not found';
exec = null;
} }
else {
_pdftotext = exec;
}
}
else {
_pdftotext = exec;
} }
} }
else { else {
exec = null;
errMsg = fileName + ' not found'; errMsg = fileName + ' not found';
} }
if (_pdftotext) { if (!exec) {
Zotero.debug('pdftotext registered at ' + _pdftotext.path); if (tool == 'converter') {
}
else {
_pdftotext = null;
Zotero.debug(errMsg + ' -- PDF indexing disabled'); Zotero.debug(errMsg + ' -- PDF indexing disabled');
} }
return false;
}
versionFile = exec.parent;
versionFile.append(fileName + '.version');
if (versionFile.exists()) {
var version = Zotero.File.getSample(versionFile).split(/[\r\n\s]/)[0];
}
if (!version) {
var version = 'UNKNOWN';
}
switch (tool) {
case 'converter':
_pdfConverter = exec;
_pdfConverterVersion = version;
break;
case 'info':
_pdfInfo = exec;
_pdfInfoVersion = version;
break;
}
Zotero.debug(toolName + ' version ' + version + ' registered at ' + exec.path);
return true;
} }
function cacheIsOutdated(){ function pdfConverterIsRegistered() {
var sql = "SELECT version FROM version WHERE schema='fulltext'"; return !!_pdfConverter;
return Zotero.DB.valueQuery(sql) < FULLTEXT_VERSION;
} }
function rebuildCache(){ function pdfInfoIsRegistered() {
Zotero.DB.beginTransaction(); return !!_pdfInfo;
Zotero.DB.query("DELETE FROM fulltextWords");
Zotero.DB.query("DELETE FROM fulltextItems");
//Zotero.DB.query("DELETE FROM fulltextContent");
var sql = "SELECT itemID FROM itemAttachments";
var items = Zotero.DB.columnQuery(sql);
if (items) {
this.indexItems(items);
}
Zotero.DB.commitTransaction();
} }
/*
* Returns true if MIME type is converted to text and cached before indexing
* (e.g. application/pdf is run through pdftotext)
*/
function isCachedMIMEType(mimeType) { function isCachedMIMEType(mimeType) {
switch (mimeType) { switch (mimeType) {
case 'application/pdf': case 'application/pdf':
@ -128,29 +195,6 @@ Zotero.Fulltext = new function(){
} }
/*
* Index a single word
*
* Note: not used
*/
function indexWord(itemID, word){
Zotero.DB.beginTransaction();
var sql = "SELECT wordID FROM fulltextWords WHERE word=?";
var wordID = Zotero.DB.valueQuery(sql, {string:word});
if (!wordID){
var sql = "INSERT INTO fulltextWords (word) VALUES (?)";
var wordID = Zotero.DB.query(sql, {string:word});
}
var sql = "INSERT OR IGNORE INTO fulltextItems VALUES (?,?)";
Zotero.DB.query(sql, [wordID, itemID]);
Zotero.DB.commitTransaction();
}
/* /*
* Index multiple words at once * Index multiple words at once
*/ */
@ -179,9 +223,12 @@ Zotero.Fulltext = new function(){
existing['_' + wordIDs[i]['word']] = wordIDs[i]['wordID']; existing['_' + wordIDs[i]['word']] = wordIDs[i]['wordID'];
} }
Zotero.DB.query("REPLACE INTO fulltextItems (itemID, version) VALUES (?,?)",
[itemID, FULLTEXT_VERSION]);
// Handle bound parameters manually for optimal speed // Handle bound parameters manually for optimal speed
var statement1 = Zotero.DB.getStatement("INSERT INTO fulltextWords (word) VALUES (?)"); var statement1 = Zotero.DB.getStatement("INSERT INTO fulltextWords (word) VALUES (?)");
var statement2 = Zotero.DB.getStatement("INSERT OR IGNORE INTO fulltextItems VALUES (?,?)"); var statement2 = Zotero.DB.getStatement("INSERT OR IGNORE INTO fulltextItemWords VALUES (?,?)");
for each(var word in words){ for each(var word in words){
if (existing['_' + word]){ if (existing['_' + word]){
@ -206,6 +253,9 @@ Zotero.Fulltext = new function(){
function indexString(text, charset, itemID){ function indexString(text, charset, itemID){
try {
Zotero.UnresponsiveScriptIndicator.disable();
var words = semanticSplitter(text, charset); var words = semanticSplitter(text, charset);
Zotero.DB.beginTransaction(); Zotero.DB.beginTransaction();
@ -220,6 +270,10 @@ Zotero.Fulltext = new function(){
Zotero.DB.commitTransaction(); Zotero.DB.commitTransaction();
} }
finally {
Zotero.UnresponsiveScriptIndicator.enable();
}
}
function indexDocument(document, itemID){ function indexDocument(document, itemID){
@ -241,20 +295,23 @@ Zotero.Fulltext = new function(){
var text = document.body.innerHTML; var text = document.body.innerHTML;
var max = Zotero.Prefs.get('fulltext.textMaxLength'); var maxLength = Zotero.Prefs.get('fulltext.textMaxLength');
if (text.length > max) { if (text.length > maxLength) {
Zotero.debug('Only indexing first ' + max + ' characters of item ' Zotero.debug('Only indexing first ' + maxLength + ' characters of item '
+ itemID + ' in indexDocument()'); + itemID + ' in indexDocument()');
text = text.substr(0, max); text = text.substr(0, maxLength);
} }
text = text.replace(/(>)/g, '$1 '); text = text.replace(/(>)/g, '$1 ');
text = this.HTMLToText(text); text = this.HTMLToText(text);
this.indexString(text, document.characterSet, itemID); this.indexString(text, document.characterSet, itemID);
var charsIndexed = Math.min(maxLength, text.length);
this.setChars(itemID, { indexed: charsIndexed, total: text.length });
} }
function indexFile(file, mimeType, charset, itemID){ function indexFile(file, mimeType, charset, itemID, maxLength, isCacheFile) {
if (!file.exists()){ if (!file.exists()){
Zotero.debug('File not found in indexFile()', 2); Zotero.debug('File not found in indexFile()', 2);
return false; return false;
@ -267,8 +324,22 @@ Zotero.Fulltext = new function(){
return false; return false;
} }
if (maxLength == undefined || maxLength === true) {
maxLength = Zotero.Prefs.get('fulltext.textMaxLength');
}
// If maxLength is explicitly false, index everything
else if (maxLength === false || maxLength === null) {
maxLength = false;
}
if (mimeType == 'application/pdf') { if (mimeType == 'application/pdf') {
return this.indexPDF(file, itemID); try {
Zotero.UnresponsiveScriptIndicator.disable();
return this.indexPDF(file, itemID, !maxLength);
}
finally {
Zotero.UnresponsiveScriptIndicator.enable();
}
} }
if (mimeType.substr(0, 5)!='text/'){ if (mimeType.substr(0, 5)!='text/'){
@ -283,23 +354,36 @@ Zotero.Fulltext = new function(){
Zotero.debug('Indexing file ' + file.path); Zotero.debug('Indexing file ' + file.path);
var maxLength = Zotero.Prefs.get('fulltext.textMaxLength');
var text = Zotero.File.getContents(file, charset, maxLength); var text = Zotero.File.getContents(file, charset, maxLength);
// Split elements to avoid word concatentation // Split elements to avoid word concatentation
text = text.replace(/(>)/g, '$1 '); text = text.replace(/(>)/g, '$1 ');
text = this.HTMLToText(text); text = this.HTMLToText(text);
this.indexString(text, charset, itemID); this.indexString(text, charset, itemID);
// Record number of characters indexed
if (!isCacheFile) {
var totalChars = this.getTotalCharsFromFile(itemID);
if (maxLength) {
var charsIndexed = Math.min(maxLength, totalChars);
}
else {
var charsIndexed = totalChars;
}
this.setChars(itemID, { indexed: charsIndexed, total: totalChars });
}
return true; return true;
} }
/* /*
* Run PDF through pdftotext to generate .zotero-ft-cache and pass the * Run PDF through pdfinfo and pdftotext to generate .zotero-ft-info
* text file back to indexFile() * and .zotero-ft-cache, and pass the text file back to indexFile()
*
* @param allPages If true, index all pages rather than pdfMaxPages
*/ */
function indexPDF(file, itemID) { function indexPDF(file, itemID, allPages) {
if (!_pdftotext) { if (!_pdfConverter) {
return false; return false;
} }
@ -313,25 +397,63 @@ Zotero.Fulltext = new function(){
else { else {
var cacheFile = file.parent; var cacheFile = file.parent;
} }
cacheFile.append(CACHE_FILE); cacheFile.append(this.pdfConverterCacheFile);
if (_pdfInfo) {
var infoFile = cacheFile.parent;
infoFile.append(this.pdfInfoCacheFile);
Zotero.debug('Running pdfinfo ' + file.path + '" "' + infoFile.path + '"');
var proc = Components.classes["@mozilla.org/process/util;1"]. var proc = Components.classes["@mozilla.org/process/util;1"].
createInstance(Components.interfaces.nsIProcess); createInstance(Components.interfaces.nsIProcess);
proc.init(_pdftotext); proc.init(_pdfInfo);
var maxPages = Zotero.Prefs.get('fulltext.pdfMaxPages');
Zotero.debug('Running pdftotext -nopgbrk -l ' + maxPages + var args = [file.path, infoFile.path];
' "' + file.path + '" "' + cacheFile.path + '"');
var args = ['-nopgbrk', '-l', maxPages, file.path, cacheFile.path];
proc.run(true, args, args.length); proc.run(true, args, args.length);
if (cacheFile.exists()) { var totalPages = this.getTotalPagesFromFile(itemID);
return this.indexFile(cacheFile, 'text/plain', 'utf-8', itemID);
} }
else {
Zotero.debug(this.pdfInfoName + " is not available");
}
var maxPages = Zotero.Prefs.get('fulltext.pdfMaxPages');
Zotero.debug('Running pdftotext -nopgbrk '
+ (allPages ? '' : '-l ' + maxPages) + ' "' + file.path + '" "'
+ cacheFile.path + '"');
var proc = Components.classes["@mozilla.org/process/util;1"].
createInstance(Components.interfaces.nsIProcess);
proc.init(_pdfConverter);
var args = ['-nopgbrk'];
if (allPages) {
if (totalPages) {
var pagesIndexed = totalPages;
}
}
else {
args.push('-l', maxPages);
var pagesIndexed = Math.min(maxPages, totalPages);
}
args.push(file.path, cacheFile.path);
proc.run(true, args, args.length);
if (!cacheFile.exists()) {
Zotero.debug("Cache file doesn't exist!");
return false; return false;
} }
Zotero.DB.beginTransaction();
this.indexFile(cacheFile, 'text/plain', 'utf-8', itemID, false, true);
this.setPages(itemID, { indexed: pagesIndexed, total: totalPages });
Zotero.DB.commitTransaction();
return true;
}
function indexItems(items){
function indexItems(items, complete) {
if (items.constructor.name != 'Array') { if (items.constructor.name != 'Array') {
items = [items]; items = [items];
} }
@ -352,12 +474,9 @@ Zotero.Fulltext = new function(){
} }
this.indexFile(file, i.getAttachmentMimeType(), this.indexFile(file, i.getAttachmentMimeType(),
i.getAttachmentCharset(), i.getID()); i.getAttachmentCharset(), i.getID(), !complete);
} }
var sql = "REPLACE INTO version (schema,version) VALUES (?,?)";
Zotero.DB.query(sql, ['fulltext', FULLTEXT_VERSION]);
Zotero.DB.commitTransaction(); Zotero.DB.commitTransaction();
} }
@ -497,10 +616,273 @@ Zotero.Fulltext = new function(){
function clearItemWords(itemID){ function clearItemWords(itemID){
Zotero.DB.beginTransaction();
Zotero.DB.query("DELETE FROM fulltextItems WHERE itemID=" + itemID); Zotero.DB.query("DELETE FROM fulltextItems WHERE itemID=" + itemID);
Zotero.DB.query("DELETE FROM fulltextItemWords WHERE itemID=" + itemID);
Zotero.DB.commitTransaction();
// Delete fulltext cache file if there is one // Delete fulltext cache file if there is one
this.clearCacheFile(itemID);
}
function getPages(itemID, force) {
var sql = "SELECT indexedPages AS indexed, totalPages AS total "
+ "FROM fulltextItems WHERE itemID=?";
var result = Zotero.DB.rowQuery(sql, itemID);
return result ? result : { indexed: null, total: null };
}
/*
* Gets the number of pages from the PDF info cache file
*/
function getTotalPagesFromFile(itemID) {
var item = Zotero.Items.get(itemID); var item = Zotero.Items.get(itemID);
var file = Zotero.Attachments.getStorageDirectory(item.getID());
file.append(this.pdfInfoCacheFile);
if (!file.exists()) {
return false;
}
var contents = Zotero.File.getContents(file);
try {
// Parse pdfinfo output
var pages = contents.match('Pages:[^0-9]+([0-9]+)')[1];
}
catch (e) {
Zotero.debug(e);
return false;
}
return pages;
}
function getChars(itemID) {
var sql = "SELECT indexedChars AS indexed, totalChars AS total "
+ "FROM fulltextItems WHERE itemID=?";
var result = Zotero.DB.rowQuery(sql, itemID);
return result ? result : { indexed: null, total: null };
}
/*
* Gets the number of characters from the PDF converter cache file
*/
function getTotalCharsFromFile(itemID) {
var item = Zotero.Items.get(itemID);
switch (item.getAttachmentMimeType()) {
case 'application/pdf':
var file = Zotero.Attachments.getStorageDirectory(itemID);
file.append(this.pdfConverterCacheFile);
if (!file.exists()) {
return false;
}
break;
default:
var file = item.getFile();
if (!file) {
return false;
}
}
return Zotero.File.getContents(file).length;
}
function setPages(itemID, obj) {
var sql = "UPDATE fulltextItems SET indexedPages=?, totalPages=? WHERE itemID=?";
Zotero.DB.query(sql, [obj.indexed ? obj.indexed : null,
obj.total ? obj.total : null, itemID]);
}
function setChars(itemID, obj) {
var sql = "UPDATE fulltextItems SET indexedChars=?, totalChars=? WHERE itemID=?";
Zotero.DB.query(sql, [obj.indexed ? obj.indexed : null,
obj.total ? obj.total : null, itemID]);
}
/*
* Gets the indexed state of an item,
*/
function getIndexedState(itemID) {
var item = Zotero.Items.get(itemID);
if (!item) {
throw ("Invalid item " + itemID + " in Zotero.Fulltext.getIndexedState()");
}
if (!item.isAttachment()) {
throw ('Item ' + itemID + ' is not an attachment in Zotero.Fulltext.getIndexedState()');
}
switch (item.getAttachmentMimeType()) {
// Use pages for PDFs
case 'application/pdf':
var pages = this.getPages(itemID);
var indexedPages = pages.indexed;
var totalPages = pages.total;
if (!totalPages) {
if (!indexedPages) {
var status = this.INDEX_STATE_UNINDEXED;
}
else {
var status = this.INDEX_STATE_UNAVAILABLE;
}
}
else if (!indexedPages) {
var status = this.INDEX_STATE_UNINDEXED;
}
else if (indexedPages < totalPages) {
var status = this.INDEX_STATE_PARTIAL;
}
else {
var status = this.INDEX_STATE_INDEXED;
}
break;
// Use chars
default:
var chars = this.getChars(itemID);
var indexedChars = chars.indexed;
var totalChars = chars.total;
if (!totalChars) {
if (!indexedChars) {
var status = this.INDEX_STATE_UNINDEXED;
}
else {
var status = this.INDEX_STATE_UNAVAILABLE;
}
}
else if (!indexedChars) {
var status = this.INDEX_STATE_UNINDEXED;
}
else if (indexedChars < totalChars) {
var status = this.INDEX_STATE_PARTIAL;
}
else {
var status = this.INDEX_STATE_INDEXED;
}
}
return status;
}
function getIndexStats() {
var sql = "SELECT COUNT(*) FROM fulltextItems WHERE "
+ "(indexedPages IS NOT NULL AND indexedPages=totalPages) OR "
+ "(indexedChars IS NOT NULL AND indexedChars=totalChars)"
var indexed = Zotero.DB.valueQuery(sql);
var sql = "SELECT COUNT(*) FROM fulltextItems WHERE "
+ "(indexedPages IS NOT NULL AND indexedPages<totalPages) OR "
+ "(indexedChars IS NOT NULL AND indexedChars<totalChars)"
var partial = Zotero.DB.valueQuery(sql);
var sql = "SELECT COUNT(*) FROM itemAttachments WHERE itemID NOT IN "
+ "(SELECT itemID FROM fulltextItems WHERE "
+ "indexedPages IS NOT NULL OR indexedChars IS NOT NULL)";
var unindexed = Zotero.DB.valueQuery(sql);
var sql = "SELECT COUNT(*) FROM fulltextWords";
var words = Zotero.DB.valueQuery(sql);
return { indexed: indexed, partial: partial, unindexed: unindexed,
words: words };
}
/*
* Returns true if an item can be reindexed
*
* Item must be a non-web-link attachment that isn't already fully indexed
*/
function canReindex(itemID) {
var item = Zotero.Items.get(itemID);
if (item && item.isAttachment() && item.getAttachmentLinkMode() !=
Zotero.Attachments.LINK_MODE_LINKED_URL) {
switch (this.getIndexedState(itemID)) {
case this.INDEX_STATE_UNAVAILABLE:
case this.INDEX_STATE_UNINDEXED:
case this.INDEX_STATE_PARTIAL:
return true;
}
}
return false;
}
function rebuildIndex(unindexedOnly){
Zotero.DB.beginTransaction();
// Get all attachments other than web links
var sql = "SELECT itemID FROM itemAttachments WHERE linkMode!="
+ Zotero.Attachments.LINK_MODE_LINKED_URL;
if (unindexedOnly) {
sql += " AND itemID NOT IN (SELECT itemID FROM fulltextItems "
+ "WHERE indexedChars IS NOT NULL OR indexedPages IS NOT NULL)";
}
var items = Zotero.DB.columnQuery(sql);
if (items) {
Zotero.DB.query("DELETE FROM fulltextItemWords WHERE itemID IN (" + sql + ")");
Zotero.DB.query("DELETE FROM fulltextItems WHERE itemID IN (" + sql + ")");
this.indexItems(items);
}
Zotero.DB.commitTransaction();
}
/*
* Clears full-text word index and all full-text cache files
*/
function clearIndex(skipLinkedURLs) {
Zotero.DB.beginTransaction();
var sql = "DELETE FROM fulltextItems";
if (skipLinkedURLs) {
var linkSQL = "SELECT itemID FROM itemAttachments WHERE linkMode ="
+ Zotero.Attachments.LINK_MODE_LINKED_URL;
sql += " WHERE itemID NOT IN (" + linkSQL + ")";
}
Zotero.DB.query(sql);
sql = "DELETE FROM fulltextItemWords";
if (skipLinkedURLs) {
sql += " WHERE itemID NOT IN (" + linkSQL + ")";
}
Zotero.DB.query(sql);
if (skipLinkedURLs) {
this.purgeUnusedWords();
}
else {
Zotero.DB.query("DELETE FROM fulltextWords");
}
this.clearCacheFiles();
Zotero.DB.commitTransaction();
}
/*
* Clears cache file for an item
*/
function clearCacheFile(itemID) {
var item = Zotero.Items.get(itemID);
if (!item) {
return;
}
if (!item.isAttachment()) {
Zotero.debug("Item " + itemID + " is not an attachment in Zotero.Fulltext.clearCacheFile()");
return;
}
Zotero.debug('Clearing full-text cache file for item ' + itemID);
switch (item.getAttachmentMimeType()) { switch (item.getAttachmentMimeType()) {
case 'application/pdf': case 'application/pdf':
var cacheFile = _getItemCacheFile(); var cacheFile = _getItemCacheFile();
@ -509,6 +891,22 @@ Zotero.Fulltext = new function(){
} }
break; break;
} }
}
/*
* Clear cache files for all attachments
*/
function clearCacheFiles(skipLinkedURLs) {
var sql = "SELECT itemID FROM itemAttachments";
if (skipLinkedURLs) {
sql += " WHERE linkMode != " + Zotero.Attachments.LINK_MODE_LINKED_URL;
}
var items = Zotero.DB.columnQuery(sql);
for (var i=0; i<items.length; i++) {
this.clearCacheFile(items[i]);
}
} }
@ -521,7 +919,7 @@ Zotero.Fulltext = new function(){
function purgeUnusedWords(){ function purgeUnusedWords(){
var sql = "DELETE FROM fulltextWords WHERE wordID NOT IN " var sql = "DELETE FROM fulltextWords WHERE wordID NOT IN "
+ "(SELECT wordID FROM fulltextItems)"; + "(SELECT wordID FROM fulltextItemWords)";
Zotero.DB.query(sql); Zotero.DB.query(sql);
} }
@ -626,7 +1024,7 @@ Zotero.Fulltext = new function(){
function _getItemCacheFile(itemID) { function _getItemCacheFile(itemID) {
var cacheFile = Zotero.getStorageDirectory(); var cacheFile = Zotero.getStorageDirectory();
cacheFile.append(itemID); cacheFile.append(itemID);
cacheFile.append(CACHE_FILE); cacheFile.append(self.pdfConverterCacheFile);
return cacheFile; return cacheFile;
} }
} }

View File

@ -237,9 +237,20 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids)
var madeChanges = false; var madeChanges = false;
var sort = false; var sort = false;
this.selection.selectEventsSuppressed = true;
var savedSelection = this.saveSelection(); var savedSelection = this.saveSelection();
// If refreshing a single item, just unselect and reselect it
if (action == 'refresh') {
if (savedSelection.length == 1 && savedSelection[0] == ids[0]) {
this.selection.clearSelection();
this.rememberSelection(savedSelection);
}
return;
}
this.selection.selectEventsSuppressed = true;
// See if we're in the active window // See if we're in the active window
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator); .getService(Components.interfaces.nsIWindowMediator);

View File

@ -82,7 +82,7 @@ Zotero.Notifier = new function(){
* Possible values: * Possible values:
* *
* event: 'add', 'modify', 'delete', 'move' ('c', for changing parent), * event: 'add', 'modify', 'delete', 'move' ('c', for changing parent),
* 'remove' (ci, it) * 'remove' (ci, it), 'refresh'
* type - 'collection', 'search', 'item', 'collection-item', 'item-tag', 'tag' * type - 'collection', 'search', 'item', 'collection-item', 'item-tag', 'tag'
* ids - single id or array of ids * ids - single id or array of ids
* *

View File

@ -119,15 +119,6 @@ Zotero.Schema = new function(){
var up2 = _updateSchema('system'); var up2 = _updateSchema('system');
var up3 = _updateSchema('scrapers'); var up3 = _updateSchema('scrapers');
// Rebuild fulltext cache if necessary
if (Zotero.Fulltext.cacheIsOutdated()){
try {
Zotero.Fulltext.rebuildCache();
}
catch (e) {
Components.utils.reportError(e);
}
}
Zotero.DB.commitTransaction(); Zotero.DB.commitTransaction();
} }
catch(e){ catch(e){
@ -1105,6 +1096,8 @@ Zotero.Schema = new function(){
} }
} }
// 1.0.0b4.r5
if (i==34) { if (i==34) {
Zotero.DB.query("ALTER TABLE annotations ADD collapsed BOOL"); Zotero.DB.query("ALTER TABLE annotations ADD collapsed BOOL");
Zotero.DB.query("ALTER TABLE annotations ADD dateModified DATETIME"); Zotero.DB.query("ALTER TABLE annotations ADD dateModified DATETIME");
@ -1112,6 +1105,23 @@ Zotero.Schema = new function(){
Zotero.DB.query("UPDATE annotations SET dateModified = DATETIME('now')"); Zotero.DB.query("UPDATE annotations SET dateModified = DATETIME('now')");
Zotero.DB.query("UPDATE highlights SET dateModified = DATETIME('now')"); Zotero.DB.query("UPDATE highlights SET dateModified = DATETIME('now')");
} }
if (i==35) {
Zotero.DB.query("CREATE TABLE fulltextItemWords (\n wordID INT,\n itemID INT,\n PRIMARY KEY (wordID, itemID),\n FOREIGN KEY (wordID) REFERENCES fulltextWords(wordID),\n FOREIGN KEY (itemID) REFERENCES items(itemID)\n);");
Zotero.DB.query("INSERT INTO fulltextItemWords SELECT * FROM fulltextItems");
Zotero.DB.query("DROP TABLE fulltextItems");
Zotero.DB.query("CREATE TABLE fulltextItems (\n itemID INT,\n version INT,\n PRIMARY KEY (itemID),\n FOREIGN KEY (itemID) REFERENCES items(itemID)\n);");
Zotero.DB.query("INSERT INTO fulltextItems SELECT DISTINCT itemID, 1 FROM fulltextItemWords");
}
if (i==36) {
Zotero.DB.query("ALTER TABLE fulltextItems ADD indexedPages INT");
Zotero.DB.query("ALTER TABLE fulltextItems ADD totalPages INT");
Zotero.DB.query("ALTER TABLE fulltextItems ADD indexedChars INT");
Zotero.DB.query("ALTER TABLE fulltextItems ADD totalChars INT");
Zotero.DB.query("DELETE FROM version WHERE schema='fulltext'");
Zotero.DB.query("VACUUM");
}
} }
_updateSchema('userdata'); _updateSchema('userdata');

View File

@ -1354,7 +1354,7 @@ Zotero.SearchConditions = new function(){
contains: true, contains: true,
doesNotContain: true doesNotContain: true
}, },
table: 'fulltextItems', table: 'fulltextItemWords',
field: 'word', field: 'word',
special: true special: true
}, },

View File

@ -122,6 +122,7 @@ var Zotero = new function(){
this.platform = win.navigator.platform; this.platform = win.navigator.platform;
this.isMac = (this.platform.substr(0, 3) == "Mac"); this.isMac = (this.platform.substr(0, 3) == "Mac");
this.isWin = (this.platform.substr(0, 3) == "Win"); this.isWin = (this.platform.substr(0, 3) == "Win");
this.isLinux = (this.platform.substr(0, 5) == "Linux");
// Locale // Locale
var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"]. var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"].

View File

@ -1,5 +1,7 @@
<!ENTITY zotero.preferences.title "Zotero Preferences"> <!ENTITY zotero.preferences.title "Zotero Preferences">
<!ENTITY zotero.preferences.default "Default:">
<!ENTITY zotero.preferences.prefpane.general "General"> <!ENTITY zotero.preferences.prefpane.general "General">
<!ENTITY zotero.preferences.userInterface "User Interface"> <!ENTITY zotero.preferences.userInterface "User Interface">
@ -27,6 +29,13 @@
<!ENTITY zotero.preferences.openurl.server "Resolver:"> <!ENTITY zotero.preferences.openurl.server "Resolver:">
<!ENTITY zotero.preferences.openurl.version "Version:"> <!ENTITY zotero.preferences.openurl.version "Version:">
<!ENTITY zotero.preferences.prefpane.search "Search">
<!ENTITY zotero.preferences.search.fulltextCache "Full-Text Cache">
<!ENTITY zotero.preferences.search.pdfIndexing "PDF Indexing">
<!ENTITY zotero.preferences.search.indexStats "Index Statistics">
<!ENTITY zotero.preferences.fulltext.textMaxLength "Maximum characters to index per file:">
<!ENTITY zotero.preferences.fulltext.pdfMaxPages "Maximum pages to index per file:">
<!ENTITY zotero.preferences.prefpane.export "Export"> <!ENTITY zotero.preferences.prefpane.export "Export">

View File

@ -1,6 +1,7 @@
general.error = Error general.error = Error
general.warning = Warning general.warning = Warning
general.dontShowWarningAgain = Don't show this warning again. general.dontShowWarningAgain = Don't show this warning again.
general.browserIsOffline = %S is currently in offline mode.
general.locate = Locate... general.locate = Locate...
general.restartRequired = Restart Required general.restartRequired = Restart Required
general.restartRequiredForChange = Firefox must be restarted for the change to take effect. general.restartRequiredForChange = Firefox must be restarted for the change to take effect.
@ -10,6 +11,12 @@ general.restartLater = Restart later
general.errorHasOccurred = An error has occurred. general.errorHasOccurred = An error has occurred.
general.restartFirefox = Please restart Firefox. general.restartFirefox = Please restart Firefox.
general.restartFirefoxAndTryAgain = Please restart Firefox and try again. general.restartFirefoxAndTryAgain = Please restart Firefox and try again.
general.checkForUpdate = Check for update
general.install = Install
general.updateAvailable = Update Available
general.upgrade = Upgrade
general.yes = Yes
general.no = No
upgrade.failed = Upgrading of the Zotero database failed: upgrade.failed = Upgrading of the Zotero database failed:
upgrade.advanceMessage = Press %S to upgrade now. upgrade.advanceMessage = Press %S to upgrade now.
@ -74,6 +81,8 @@ pane.items.menu.createBib = Create Bibliography from Selected Item...
pane.items.menu.createBib.multiple = Create Bibliography from Selected Items... pane.items.menu.createBib.multiple = Create Bibliography from Selected Items...
pane.items.menu.generateReport = Generate Report from Selected Item... pane.items.menu.generateReport = Generate Report from Selected Item...
pane.items.menu.generateReport.multiple = Generate Report from Selected Items... pane.items.menu.generateReport.multiple = Generate Report from Selected Items...
pane.items.menu.reindexItem = Reindex Item
pane.items.menu.reindexItem.multiple = Reindex Items
pane.item.selected.zero = No items selected pane.item.selected.zero = No items selected
pane.item.selected.multiple = %S items selected pane.item.selected.multiple = %S items selected
@ -313,6 +322,29 @@ zotero.preferences.update.error = Error
zotero.preferences.openurl.resolversFound.zero = %S resolvers found zotero.preferences.openurl.resolversFound.zero = %S resolvers found
zotero.preferences.openurl.resolversFound.singular = %S resolver found zotero.preferences.openurl.resolversFound.singular = %S resolver found
zotero.preferences.openurl.resolversFound.plural = %S resolvers found zotero.preferences.openurl.resolversFound.plural = %S resolvers found
zotero.preferences.search.rebuildIndex = Rebuild Index
zotero.preferences.search.rebuildWarning = Do you want to rebuild the entire index? This may take a while.\n\nTo index only items that haven't been indexed, use %S.
zotero.preferences.search.clearIndex = Clear Index
zotero.preferences.search.clearWarning = After clearing the index, attachment content will no longer be searchable.\n\nWeb link attachments cannot be reindexed without revisiting the page. To leave web links indexed, choose %S.
zotero.preferences.search.clearNonLinkedURLs = Clear All Except Web Links
zotero.preferences.search.indexUnindexed = Index Unindexed Items
zotero.preferences.search.pdf.toolRegistered = %S is installed
zotero.preferences.search.pdf.toolNotRegistered = %S is NOT installed
zotero.preferences.search.pdf.toolsRequired = PDF indexing requires the %1$S and %2$S utilities from the %3$S project.
zotero.preferences.search.pdf.automaticInstall = Zotero can automatically download and install these applications from zotero.org for certain platforms.
zotero.preferences.search.pdf.advancedUsers = Advanced users may wish to view the %S for manual installation instructions.
zotero.preferences.search.pdf.documentationLink = documentation
zotero.preferences.search.pdf.checkForInstaller = Check for installer
zotero.preferences.search.pdf.downloading = Downloading...
zotero.preferences.search.pdf.toolDownloadsNotAvailable = The %S utilities are not currently available for your platform via zotero.org.
zotero.preferences.search.pdf.viewManualInstructions = View the documentation for manual installation instructions.
zotero.preferences.search.pdf.availableDownloads = Available downloads for %1$S from %2$S:
zotero.preferences.search.pdf.availableUpdates = Available updates for %1$S from %2$S:
zotero.preferences.search.pdf.toolVersionPlatform = %1$S version %2$S
zotero.preferences.search.pdf.zoteroCanInstallVersion = Zotero can automatically install it into the Zotero data directory.
zotero.preferences.search.pdf.zoteroCanInstallVersions = Zotero can automatically install these applications into the Zotero data directory.
zotero.preferences.search.pdf.toolsDownloadError = An error occurred while attempting to download the %S utilities from zotero.org.
zotero.preferences.search.pdf.tryAgainOrViewManualInstructions = Please try again later, or view the documentation for manual installation instructions.
zotero.preferences.export.quickCopy.bibStyles = Bibliographic Styles zotero.preferences.export.quickCopy.bibStyles = Bibliographic Styles
zotero.preferences.export.quickCopy.exportFormats = Export Formats zotero.preferences.export.quickCopy.exportFormats = Export Formats
zotero.preferences.export.quickCopy.instructions = Quick Copy allows you to copy selected references to the clipboard by pressing a shortcut key (%S) or dragging items into a text box on a web page. zotero.preferences.export.quickCopy.instructions = Quick Copy allows you to copy selected references to the clipboard by pressing a shortcut key (%S) or dragging items into a text box on a web page.
@ -371,6 +403,9 @@ searchConditions.fulltextContent = Attachment Content
searchConditions.programmingLanguage = Programming Language searchConditions.programmingLanguage = Programming Language
searchConditions.fileTypeID = Attachment File Type searchConditions.fileTypeID = Attachment File Type
fulltext.indexState.indexed = Indexed
fulltext.indexState.unavailable = Unknown
fulltext.indexState.partial = Partial
exportOptions.exportNotes = Export Notes exportOptions.exportNotes = Export Notes
exportOptions.exportFileData = Export Files exportOptions.exportFileData = Export Files

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

View File

@ -233,6 +233,27 @@
-moz-box-flex: 1; -moz-box-flex: 1;
} }
/* Reindex button in attachment pane */
#zotero-attachment-index-box
{
-moz-box-align: center;
}
#zotero-attachment-reindex
{
margin: 0;
padding: 0;
list-style-image: url(chrome://zotero/skin/arrow_refresh.png);
}
#zotero-attachment-reindex .toolbarbutton-icon
{
margin: 0;
padding: 0;
}
#zotero-go-to-url[disabled=true], #zotero-openurl[disabled=true] #zotero-go-to-url[disabled=true], #zotero-openurl[disabled=true]
{ {
list-style-image: url('chrome://zotero/skin/toolbar-go-arrow-disabled.png'); list-style-image: url('chrome://zotero/skin/toolbar-go-arrow-disabled.png');
@ -250,6 +271,18 @@
min-height: 1.25em; min-height: 1.25em;
} }
#zotero-attachment-index-box
{
-moz-box-align: center;
}
#zotero-attachment-index-box > button
{
font-size: .95em;
padding: 0;
}
#zotero-splitter #zotero-splitter
{ {
border-top: none; border-top: none;

View File

@ -3,6 +3,16 @@ prefwindow .chromeclass-toolbar
display: -moz-box !important; /* Ignore toolbar collapse button on OS X */ display: -moz-box !important; /* Ignore toolbar collapse button on OS X */
} }
/* Prevent bugs in automatic prefpane sizing in Firefox 2.0
From http://forums.mozillazine.org/viewtopic.php?p=2883233&sid=e1285f81ea9c824363802ea5ca96c9b2
*/
prefwindow {
width: 45em;
}
prefwindow > prefpane > vbox.content-box {
height: 42em;
}
radio[pane] radio[pane]
{ {
min-width: 5.5em; min-width: 5.5em;
@ -11,46 +21,64 @@ radio[pane]
-moz-box-pack: end; -moz-box-pack: end;
} }
/* General pane icon */ /* Remove extraneous padding */
vbox > *:first-child
{
margin-top: 0;
}
vbox > *:last-child
{
margin-bottom: 0;
}
hbox > *:first-child
{
margin-left: 0;
}
/*
hbox
{
-moz-outline: 1px dashed green;
}
vbox
{
-moz-outline: 1px dashed yellow;
}
label
{
-moz-outline: 1px dashed pink;
}
*/
/* Links within messages */
label label[class=text-link]
{
margin: 0;
}
/* General pane */
radio[pane=zotero-prefpane-general] radio[pane=zotero-prefpane-general]
{ {
list-style-image: url("chrome://zotero/skin/prefs-general.png"); list-style-image: url("chrome://zotero/skin/prefs-general.png");
} }
/* grid row:not(:first-child)
* Export pane icon
*/
radio[pane=zotero-prefpane-export]
{ {
list-style-image: url("chrome://zotero/skin/prefs-export.png"); margin-top: .3em;
} }
/*
* Shortcut Keys pane icon
*
* Use the Gear icon until we find a keyboard icon
*/
radio[pane=zotero-prefpane-keys]
{
list-style-image: url("chrome://zotero/skin/prefs-keys.png");
}
/*
* Advanced pane icon
*
* Use the Gear icon until we find a better icon
*/
radio[pane=zotero-prefpane-advanced]
{
list-style-image: url("chrome://zotero/skin/prefs-advanced.png");
}
/* General pane */
grid row hbox:first-child grid row hbox:first-child
{ {
-moz-box-pack: end; -moz-box-pack: end; /* Right-justify left column */
}
#position-menu-box-label, #position-menu-box
{
-moz-box-align: center;
} }
#fontSize #fontSize
@ -90,7 +118,51 @@ grid row hbox:first-child
} }
/*
* Search pane
*/
radio[pane=zotero-prefpane-search]
{
list-style-image: url("chrome://zotero/skin/prefs-search.png");
}
#zotero-prefpane-search groupbox > label, #zotero-prefpane-search groupbox > vbox, #zotero-prefpane-search groupbox > hbox
{
margin: .5em 0;
}
#zotero-prefpane-search groupbox > label:first-child
{
margin-top: 0;
}
#pdfinfo-status
{
margin-top: 0 !important;
}
#fulltext-settings hbox, #pdftools-settings hbox
{
-moz-box-align: center;
}
#fulltext-settings row > hbox:last-child, #pdftools-settings row > hbox:last-child
{
margin-left: .5em;
}
#fulltext-stats row > label:first-child
{
text-align: right;
}
/* Export pane */ /* Export pane */
radio[pane=zotero-prefpane-export]
{
list-style-image: url("chrome://zotero/skin/prefs-export.png");
}
#quickCopy-instructions, #zotero-prefpane-export vbox { #quickCopy-instructions, #zotero-prefpane-export vbox {
margin-bottom: 1em; margin-bottom: 1em;
} }
@ -119,6 +191,11 @@ grid row hbox:first-child
/* Shortcut Keys pane */ /* Shortcut Keys pane */
radio[pane=zotero-prefpane-keys]
{
list-style-image: url("chrome://zotero/skin/prefs-keys.png");
}
#zotero-prefpane-keys row #zotero-prefpane-keys row
{ {
-moz-box-align: center; -moz-box-align: center;
@ -139,3 +216,12 @@ grid row hbox:first-child
margin: .75em 0; margin: .75em 0;
font-size: .85em; font-size: .85em;
} }
/*
* Advanced pane
*/
radio[pane=zotero-prefpane-advanced]
{
list-style-image: url("chrome://zotero/skin/prefs-advanced.png");
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,4 +1,4 @@
-- 34 -- 36
-- This file creates tables containing user-specific data -- any changes -- This file creates tables containing user-specific data -- any changes
-- to existing tables made here must be mirrored in transition steps in -- to existing tables made here must be mirrored in transition steps in
@ -205,18 +205,32 @@ CREATE TABLE IF NOT EXISTS savedSearchConditions (
FOREIGN KEY (savedSearchID) REFERENCES savedSearches(savedSearchID) FOREIGN KEY (savedSearchID) REFERENCES savedSearches(savedSearchID)
); );
CREATE TABLE IF NOT EXISTS fulltextItems (
itemID INT,
version INT,
indexedPages INT,
totalPages INT,
indexedChars INT,
totalChars INT,
PRIMARY KEY (itemID),
FOREIGN KEY (itemID) REFERENCES items(itemID)
);
CREATE INDEX IF NOT EXISTS fulltextItems_version ON fulltextItems(version);
CREATE TABLE IF NOT EXISTS fulltextWords ( CREATE TABLE IF NOT EXISTS fulltextWords (
wordID INTEGER PRIMARY KEY, wordID INTEGER PRIMARY KEY,
word TEXT UNIQUE word TEXT UNIQUE
); );
CREATE INDEX IF NOT EXISTS fulltextWords_word ON fulltextWords(word); CREATE INDEX IF NOT EXISTS fulltextWords_word ON fulltextWords(word);
CREATE TABLE IF NOT EXISTS fulltextItems ( CREATE TABLE IF NOT EXISTS fulltextItemWords (
wordID INT, wordID INT,
itemID INT, itemID INT,
PRIMARY KEY (wordID, itemID) PRIMARY KEY (wordID, itemID),
FOREIGN KEY (wordID) REFERENCES fulltextWords(wordID),
FOREIGN KEY (itemID) REFERENCES items(itemID)
); );
CREATE INDEX IF NOT EXISTS fulltextItems_itemID ON fulltextItems(itemID); CREATE INDEX IF NOT EXISTS fulltextItemWords_itemID ON fulltextItemWords(itemID);
CREATE TABLE IF NOT EXISTS translators ( CREATE TABLE IF NOT EXISTS translators (
translatorID TEXT PRIMARY KEY, translatorID TEXT PRIMARY KEY,