commit fc857dc496415669f8cb58a3dcaad31801f5aa36
parent 893b9ae1fc334dea13e5394ded3c950c2ce115c3
Author: Dan Stillman <dstillman@zotero.org>
Date: Sat, 2 Jul 2016 01:46:23 -0400
Close #1053, Manual sync option in library context menu
This also reworks how the collection context menu is built to do more in
JS instead of XUL, though it can't do it all in JS because some
localized strings are in zotero.dtd and are used in standalone.xul too.
Diffstat:
3 files changed, 226 insertions(+), 113 deletions(-)
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
@@ -2313,7 +2313,111 @@ var ZoteroPane = new function()
this.buildCollectionContextMenu = function (noRepeat) {
+ var libraryID = this.getSelectedLibraryID();
+
+ // menuitem configuration
+ //
+ // This has to be kept in sync with zotero-collectionmenu in zoteroPane.xul. We could do this
+ // entirely in JS, but various localized strings are only in zotero.dtd, and they're used in
+ // standalone.xul as well, so for now they have to remain as XML entities.
+ var options = [
+ {
+ id: "sync",
+ label: Zotero.getString('sync.sync'),
+ onclick: () => {
+ Zotero.Sync.Runner.sync({
+ libraries: [libraryID],
+ });
+ }
+ },
+ {
+ id: "sep1",
+ },
+ {
+ id: "newCollection",
+ command: "cmd_zotero_newCollection"
+ },
+ {
+ id: "newSavedSearch",
+ command: "cmd_zotero_newSavedSearch"
+ },
+ {
+ id: "newSubcollection",
+ onclick: () => {
+ this.newCollection(this.getSelectedCollection().key);
+ }
+ },
+ {
+ id: "refreshFeed",
+ onclick: () => this.refreshFeed()
+ },
+ {
+ id: "sep2",
+ },
+ {
+ id: "showDuplicates",
+ onclick: () => {
+ this.setVirtual(libraryID, 'duplicates', true);
+ }
+ },
+ {
+ id: "showUnfiled",
+ onclick: () => {
+ this.setVirtual(libraryID, 'unfiled', true);
+ }
+ },
+ {
+ id: "editSelectedCollection",
+ onclick: () => this.editSelectedCollection()
+ },
+ {
+ id: "markReadFeed",
+ onclick: () => this.markFeedRead()
+ },
+ {
+ id: "editSelectedFeed",
+ onclick: () => this.editSelectedFeed()
+ },
+ {
+ id: "deleteCollection",
+ onclick: () => this.deleteSelectedCollection()
+ },
+ {
+ id: "deleteCollectionAndItems",
+ onclick: () => this.deleteSelectedCollection(true)
+ },
+ {
+ id: "sep3",
+ },
+ {
+ id: "exportCollection",
+ onclick: () => Zotero_File_Interface.exportCollection()
+ },
+ {
+ id: "createBibCollection",
+ onclick: () => Zotero_File_Interface.bibliographyFromCollection()
+ },
+ {
+ id: "exportFile",
+ onclick: () => Zotero_File_Interface.exportFile()
+ },
+ {
+ id: "loadReport",
+ onclick: event => Zotero_Report_Interface.loadCollectionReport(event)
+ },
+ {
+ id: "emptyTrash",
+ onclick: () => this.emptyTrash()
+ }
+ ];
+
+
var collectionTreeRow = this.collectionsView.selectedTreeRow;
+ // This can happen if selection is changing during delayed second call below
+ if (!collectionTreeRow) {
+ return;
+ }
+
// If the items view isn't initialized, this was a right-click on a different collection and
// the new collection's items are still loading, so update the menu after loading. This causes
// some menu items (e.g., export/createBib/loadReport) to appear gray in the menu at first and
@@ -2324,169 +2428,174 @@ var ZoteroPane = new function()
}.bind(this));
}
- var options = [
- "newCollection",
- "newSavedSearch",
- "newSubcollection",
- "refreshFeed",
- "sep1",
- "showDuplicates",
- "showUnfiled",
- "editSelectedCollection",
- "markReadFeed",
- "editSelectedFeed",
- "deleteCollection",
- "deleteCollectionAndItems",
- "sep2",
- "exportCollection",
- "createBibCollection",
- "exportFile",
- "loadReport",
- "emptyTrash",
- "createCommonsBucket",
- "refreshCommonsBucket"
- ];
-
+ // Set attributes on the menu from the configuration object
+ var menu = document.getElementById('zotero-collectionmenu');
var m = {};
for (let i = 0; i < options.length; i++) {
- m[options[i]] = i;
+ let option = options[i];
+ let menuitem = menu.childNodes[i];
+ m[option.id] = menuitem;
+
+ menuitem.id = option.id;
+ if (!menuitem.classList.contains('menuitem-iconic')) {
+ menuitem.classList.add('menuitem-iconic');
+ }
+ if (option.label) {
+ menuitem.setAttribute('label', option.label);
+ }
+ if (option.command) {
+ menuitem.setAttribute('command', option.command);
+ }
+ else if (option.onclick) {
+ menuitem.onclick = option.onclick;
+ }
}
- var menu = document.getElementById('zotero-collectionmenu');
-
// By default things are hidden and visible, so we only need to record
// when things are visible and when they're visible but disabled
var show = [], disable = [];
if (collectionTreeRow.isCollection()) {
show = [
- m.newSubcollection,
- m.sep1,
- m.editSelectedCollection,
- m.deleteCollection,
- m.deleteCollectionAndItems,
- m.sep2,
- m.exportCollection,
- m.createBibCollection,
- m.loadReport
+ 'newSubcollection',
+ 'sep2',
+ 'editSelectedCollection',
+ 'deleteCollection',
+ 'deleteCollectionAndItems',
+ 'sep3',
+ 'exportCollection',
+ 'createBibCollection',
+ 'loadReport'
];
- var s = [m.exportCollection, m.createBibCollection, m.loadReport];
if (!this.itemsView.rowCount) {
- disable = s;
+ disable = ['exportCollection', 'createBibCollection', 'loadReport'];
}
// Adjust labels
- menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.rename.collection'));
- menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('pane.collections.menu.delete.collection'));
- menu.childNodes[m.deleteCollectionAndItems].setAttribute('label', Zotero.getString('pane.collections.menu.delete.collectionAndItems'));
- menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.collection'));
- menu.childNodes[m.createBibCollection].setAttribute('label', Zotero.getString('pane.collections.menu.createBib.collection'));
- menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.collection'));
+ m.editSelectedCollection.setAttribute('label', Zotero.getString('pane.collections.menu.rename.collection'));
+ m.deleteCollection.setAttribute('label', Zotero.getString('pane.collections.menu.delete.collection'));
+ m.deleteCollectionAndItems.setAttribute('label', Zotero.getString('pane.collections.menu.delete.collectionAndItems'));
+ m.exportCollection.setAttribute('label', Zotero.getString('pane.collections.menu.export.collection'));
+ m.createBibCollection.setAttribute('label', Zotero.getString('pane.collections.menu.createBib.collection'));
+ m.loadReport.setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.collection'));
}
else if (collectionTreeRow.isFeed()) {
show = [
- m.refreshFeed,
- m.sep1,
- m.markReadFeed,
- m.editSelectedFeed,
- m.deleteCollectionAndItems
+ 'refreshFeed',
+ 'sep2',
+ 'markReadFeed',
+ 'editSelectedFeed',
+ 'deleteCollectionAndItems'
];
if (collectionTreeRow.ref.unreadCount == 0) {
- disable.push(m.markReadFeed);
+ disable = ['markReadFeed'];
}
// Adjust labels
- menu.childNodes[m.deleteCollectionAndItems].setAttribute('label', Zotero.getString('pane.collections.menu.delete.feedAndItems'));
+ m.deleteCollectionAndItems.setAttribute('label', Zotero.getString('pane.collections.menu.delete.feedAndItems'));
}
else if (collectionTreeRow.isSearch()) {
show = [
- m.editSelectedCollection,
- m.deleteCollection,
- m.sep2,
- m.exportCollection,
- m.createBibCollection,
- m.loadReport
+ 'editSelectedCollection',
+ 'deleteCollection',
+ 'sep3',
+ 'exportCollection',
+ 'createBibCollection',
+ 'loadReport'
];
- menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('pane.collections.menu.delete.savedSearch'));
+ m.deleteCollection.setAttribute('label', Zotero.getString('pane.collections.menu.delete.savedSearch'));
- var s = [m.exportCollection, m.createBibCollection, m.loadReport];
if (!this.itemsView.rowCount) {
- disable = s;
+ disable.push('exportCollection', 'createBibCollection', 'loadReport');
}
// Adjust labels
- menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch'));
- menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.savedSearch'));
- menu.childNodes[m.createBibCollection].setAttribute('label', Zotero.getString('pane.collections.menu.createBib.savedSearch'));
- menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.savedSearch'));
+ m.editSelectedCollection.setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch'));
+ m.exportCollection.setAttribute('label', Zotero.getString('pane.collections.menu.export.savedSearch'));
+ m.createBibCollection.setAttribute('label', Zotero.getString('pane.collections.menu.createBib.savedSearch'));
+ m.loadReport.setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.savedSearch'));
}
else if (collectionTreeRow.isTrash()) {
- show = [m.emptyTrash];
+ show = ['emptyTrash'];
}
else if (collectionTreeRow.isDuplicates() || collectionTreeRow.isUnfiled()) {
- show = [
- m.deleteCollection
- ];
+ show = ['deleteCollection'];
- menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('general.hide'));
+ m.deleteCollection.setAttribute('label', Zotero.getString('general.hide'));
}
else if (collectionTreeRow.isHeader()) {
- if (collectionTreeRow.ref.id == 'commons-header') {
- show = [m.createCommonsBucket];
- }
- }
- else if (collectionTreeRow.isBucket()) {
- show = [m.refreshCommonsBucket];
}
else if (collectionTreeRow.isPublications()) {
- show = [m.exportFile];
+ show = [
+ 'sync',
+ 'sep1',
+ 'exportFile'
+ ];
}
// Library
else {
show = [
- m.newCollection,
- m.newSavedSearch,
- m.sep1,
- m.showDuplicates,
- m.showUnfiled,
- m.sep2,
- m.exportFile
+ 'sync',
+ 'sep1',
+ 'newCollection',
+ 'newSavedSearch',
];
+ // Only show "Show Duplicates" and "Show Unfiled Items" if rows are hidden
+ let duplicates = Zotero.Utilities.Internal.getVirtualCollectionStateForLibrary(
+ libraryID, 'duplicates'
+ );
+ let unfiled = Zotero.Utilities.Internal.getVirtualCollectionStateForLibrary(
+ libraryID, 'unfiled'
+ );
+ if (!duplicates || !unfiled) {
+ show.push('sep2');
+ if (!duplicates) {
+ show.push('showDuplicates');
+ }
+ if (!unfiled) {
+ show.push('showUnfiled');
+ }
+ }
+ show.push(
+ 'sep3',
+ 'exportFile'
+ );
}
// Disable some actions if user doesn't have write access
//
// Some actions are disabled via their commands in onCollectionSelected()
- var s = [m.newSubcollection, m.editSelectedCollection, m.deleteCollection, m.deleteCollectionAndItems];
if (collectionTreeRow.isWithinGroup() && !collectionTreeRow.editable && !collectionTreeRow.isDuplicates() && !collectionTreeRow.isUnfiled()) {
- disable = disable.concat(s);
+ disable.push(
+ 'newSubcollection',
+ 'editSelectedCollection',
+ 'deleteCollection',
+ 'deleteCollectionAndItems'
+ );
}
// If within non-editable group or trash it empty, disable Empty Trash
if (collectionTreeRow.isTrash()) {
if ((collectionTreeRow.isWithinGroup() && !collectionTreeRow.isWithinEditableGroup()) || !this.itemsView.rowCount) {
- disable.push(m.emptyTrash);
+ disable.push('emptyTrash');
}
}
// Hide and enable all actions by default (so if they're shown they're enabled)
for (let i in m) {
- let pos = m[i];
- menu.childNodes[pos].setAttribute('hidden', true);
- menu.childNodes[pos].setAttribute('disabled', false);
+ m[i].setAttribute('hidden', true);
+ m[i].setAttribute('disabled', false);
}
- for (var i in show)
- {
- menu.childNodes[show[i]].setAttribute('hidden', false);
+ for (let id of show) {
+ m[id].setAttribute('hidden', false);
}
- for (var i in disable)
- {
- menu.childNodes[disable[i]].setAttribute('disabled', true);
+ for (let id of disable) {
+ m[id].setAttribute('disabled', true);
}
}
diff --git a/chrome/content/zotero/zoteroPane.xul b/chrome/content/zotero/zoteroPane.xul
@@ -256,27 +256,27 @@
<popupset>
<menupopup id="zotero-collectionmenu" onpopupshowing="ZoteroPane_Local.buildCollectionContextMenu();">
- <!-- Keep order in sync with buildCollectionContextMenu -->
- <menuitem class="menuitem-iconic zotero-menuitem-new-collection" label="&zotero.toolbar.newCollection.label;" command="cmd_zotero_newCollection"/>
- <menuitem class="menuitem-iconic zotero-menuitem-new-saved-search" label="&zotero.toolbar.newSavedSearch.label;" command="cmd_zotero_newSavedSearch"/>
- <menuitem class="menuitem-iconic zotero-menuitem-new-collection" label="&zotero.toolbar.newSubcollection.label;" oncommand="ZoteroPane_Local.newCollection(ZoteroPane_Local.getSelectedCollection().key)"/>
- <menuitem class="menuitem-iconic zotero-menuitem-refresh-feed" label="&zotero.toolbar.feeds.refresh;" oncommand="ZoteroPane_Local.refreshFeed();"/>
+ <!-- Keep order in sync with buildCollectionContextMenu, which adds additional attributes -->
+ <menuitem class="zotero-menuitem-sync"/>
<menuseparator/>
- <menuitem class="menuitem-iconic zotero-menuitem-show-duplicates" label="&zotero.toolbar.duplicate.label;" oncommand="ZoteroPane_Local.setVirtual(ZoteroPane_Local.getSelectedLibraryID(), 'duplicates', true)"/>
- <menuitem class="menuitem-iconic zotero-menuitem-show-unfiled" label="&zotero.collections.showUnfiledItems;" oncommand="ZoteroPane_Local.setVirtual(ZoteroPane_Local.getSelectedLibraryID(), 'unfiled', true)"/>
- <menuitem class="menuitem-iconic zotero-menuitem-edit-collection" oncommand="ZoteroPane_Local.editSelectedCollection();"/>
- <menuitem class="menuitem-iconic zotero-menuitem-mark-read-feed" label="&zotero.toolbar.markFeedRead.label;" oncommand="ZoteroPane_Local.markFeedRead();"/>
- <menuitem class="menuitem-iconic zotero-menuitem-edit-feed" label="&zotero.toolbar.feeds.edit;" oncommand="ZoteroPane_Local.editSelectedFeed();"/>
- <menuitem class="menuitem-iconic zotero-menuitem-delete-collection" oncommand="ZoteroPane_Local.deleteSelectedCollection();"/>
- <menuitem class="menuitem-iconic zotero-menuitem-move-to-trash" oncommand="ZoteroPane_Local.deleteSelectedCollection(true);"/>
+ <menuitem class="zotero-menuitem-new-collection" label="&zotero.toolbar.newCollection.label;"/>
+ <menuitem class="zotero-menuitem-new-saved-search" label="&zotero.toolbar.newSavedSearch.label;"/>
+ <menuitem class="zotero-menuitem-new-collection" label="&zotero.toolbar.newSubcollection.label;"/>
+ <menuitem class="zotero-menuitem-refresh-feed" label="&zotero.toolbar.feeds.refresh;"/>
<menuseparator/>
- <menuitem class="menuitem-iconic zotero-menuitem-export" oncommand="Zotero_File_Interface.exportCollection();"/>
- <menuitem class="menuitem-iconic zotero-menuitem-create-bibliography" oncommand="Zotero_File_Interface.bibliographyFromCollection();"/>
- <menuitem class="menuitem-iconic zotero-menuitem-export" label="&zotero.toolbar.export.label;" oncommand="Zotero_File_Interface.exportFile()"/>
- <menuitem class="menuitem-iconic zotero-menuitem-create-report" oncommand="Zotero_Report_Interface.loadCollectionReport(event)"/>
- <menuitem class="menuitem-iconic zotero-menuitem-delete-from-lib" label="&zotero.toolbar.emptyTrash.label;" oncommand="ZoteroPane_Local.emptyTrash();"/>
- <menuitem label="&zotero.toolbar.newCollection.label;" oncommand="ZoteroPane_Local.createCommonsBucket();"/><!--TODO localize -->
- <menuitem label="Refresh" oncommand="ZoteroPane_Local.refreshCommonsBucket();"/><!--TODO localize -->
+ <menuitem class="zotero-menuitem-show-duplicates" label="&zotero.toolbar.duplicate.label;"/>
+ <menuitem class="zotero-menuitem-show-unfiled" label="&zotero.collections.showUnfiledItems;"/>
+ <menuitem class="zotero-menuitem-edit-collection"/>
+ <menuitem class="zotero-menuitem-mark-read-feed" label="&zotero.toolbar.markFeedRead.label;"/>
+ <menuitem class="zotero-menuitem-edit-feed" label="&zotero.toolbar.feeds.edit;"/>
+ <menuitem class="zotero-menuitem-delete-collection"/>
+ <menuitem class="zotero-menuitem-move-to-trash"/>
+ <menuseparator/>
+ <menuitem class="zotero-menuitem-export"/>
+ <menuitem class="zotero-menuitem-create-bibliography"/>
+ <menuitem class="zotero-menuitem-export" label="&zotero.toolbar.export.label;"/>
+ <menuitem class="zotero-menuitem-create-report"/>
+ <menuitem class="zotero-menuitem-delete-from-lib" label="&zotero.toolbar.emptyTrash.label;"/>
</menupopup>
<menupopup id="zotero-itemmenu">
<!-- Keep order in sync with buildItemContextMenu -->
diff --git a/chrome/skin/default/zotero/overlay.css b/chrome/skin/default/zotero/overlay.css
@@ -397,6 +397,10 @@
list-style-image: url('chrome://zotero/skin/treesource-unfiled.png');
}
+.zotero-menuitem-sync {
+ list-style-image: url(chrome://zotero/skin/arrow_rotate_static.png);
+}
+
.zotero-menuitem-new-collection
{
list-style-image: url('chrome://zotero/skin/toolbar-collection-add.png');