diff --git a/chrome/content/zotero/xpcom/collectionTreeView.js b/chrome/content/zotero/xpcom/collectionTreeView.js
index 2dce05c29..c8826a7bc 100644
--- a/chrome/content/zotero/xpcom/collectionTreeView.js
+++ b/chrome/content/zotero/xpcom/collectionTreeView.js
@@ -74,76 +74,13 @@ Zotero.CollectionTreeView.prototype.setTree = function(treebox)
this.refresh();
- // Select the last-viewed collection
- var lastViewedFolder = Zotero.Prefs.get('lastViewedFolder');
- var matches = lastViewedFolder.match(/^(?:(C|S|G)([0-9]+)|L)$/);
- var select = 0;
- if (matches) {
- if (matches[1] == 'C') {
- if (this._collectionRowMap[matches[2]]) {
- select = this._collectionRowMap[matches[2]];
- }
- // Search recursively
- else {
- var path = [];
- var failsafe = 10; // Only go up ten levels
- var lastCol = matches[2];
- do {
- failsafe--;
- var col = Zotero.Collections.get(lastCol);
- if (!col) {
- var msg = "Last-viewed collection not found";
- Zotero.debug(msg);
- path = [];
- break;
- }
- var par = col.getParent();
- if (!par) {
- var msg = "Parent collection not found in "
- + "Zotero.CollectionTreeView.setTree()";
- Zotero.debug(msg, 1);
- Components.utils.reportError(msg);
- path = [];
- break;
- }
- lastCol = par;
- path.push(lastCol);
- }
- while (!this._collectionRowMap[lastCol] && failsafe > 0)
- if (path.length) {
- for (var i=path.length-1; i>=0; i--) {
- var id = path[i];
- var row = this._collectionRowMap[id];
- if (!row) {
- var msg = "Collection not found in tree in "
- + "Zotero.CollectionTreeView.setTree()";
- Zotero.debug(msg, 1);
- Components.utils.reportError(msg);
- break;
- }
- if (!this.isContainerOpen(row)) {
- this.toggleOpenState(row);
- if (this._collectionRowMap[matches[2]]) {
- select = this._collectionRowMap[matches[2]];
- break;
- }
- }
- }
- }
- }
- }
- else if (matches[1] == 'S' && this._searchRowMap[matches[2]]) {
- select = this._searchRowMap[matches[2]];
- }
- else if (matches[1] == 'G' && this._groupRowMap[matches[2]]) {
- select = this._groupRowMap[matches[2]];
- }
- }
-
this.selection.currentColumn = this._treebox.columns.getFirstColumn();
- this.selection.select(select);
+
+ var row = this.getLastViewedRow();
+ this.selection.select(row);
}
+
/*
* Reload the rows from the data access methods
* (doesn't call the tree.invalidate methods, etc.)
@@ -165,6 +102,13 @@ Zotero.CollectionTreeView.prototype.refresh = function()
this._dataItems = [];
this.rowCount = 0;
+ try {
+ var unfiledLibraries = Zotero.Prefs.get('unfiledLibraries').split(',');
+ }
+ catch (e) {
+ unfiledLibraries = [];
+ }
+
var self = this;
var library = {
id: null,
@@ -190,6 +134,18 @@ Zotero.CollectionTreeView.prototype.refresh = function()
}
}
+ // Unfiled items
+ if (unfiledLibraries.indexOf('0') != -1) {
+ var s = new Zotero.Search;
+ // Give virtual search an id so it can be reselected automatically
+ s.id = 86345330000; // 'UNFILED' + '000' + libraryID
+ s.name = Zotero.getString('pane.collections.unfiled');
+ s.addCondition('libraryID', 'is', null);
+ s.addCondition('unfiled', 'true');
+ self._showItem(new Zotero.ItemGroup('search', s), 1, newRows+1);
+ newRows++;
+ }
+
var deletedItems = Zotero.Items.getDeleted();
if (deletedItems || Zotero.Prefs.get("showTrashWhenEmpty")) {
self._showItem(new Zotero.ItemGroup('trash', false), 1, newRows+1);
@@ -236,6 +192,18 @@ Zotero.CollectionTreeView.prototype.refresh = function()
newRows++;
}
}
+
+ // Unfiled items
+ if (unfiledLibraries.indexOf(groups[i].libraryID + '') != -1) {
+ var s = new Zotero.Search;
+ s.id = parseInt('8634533000' + groups[i].libraryID); // 'UNFILED' + '000' + libraryID
+ s.libraryID = groups[i].libraryID;
+ s.name = Zotero.getString('pane.collections.unfiled');
+ s.addCondition('libraryID', 'is', groups[i].libraryID);
+ s.addCondition('unfiled', 'true');
+ self._showItem(new Zotero.ItemGroup('search', s), 2);
+ newRows++;
+ }
}
}
};
@@ -270,8 +238,6 @@ Zotero.CollectionTreeView.prototype.refresh = function()
}
}
};
- Zotero.debug('=============');
- Zotero.debug(commonsExpand);
this._showItem(new Zotero.ItemGroup('header', header), null, null, commonsExpand);
if (commonsExpand) {
header.expand();
@@ -781,6 +747,78 @@ Zotero.CollectionTreeView.prototype.selectLibrary = function (libraryID) {
return false;
}
+/**
+ * Select the last-viewed source
+ */
+Zotero.CollectionTreeView.prototype.getLastViewedRow = function () {
+ var lastViewedFolder = Zotero.Prefs.get('lastViewedFolder');
+ var matches = lastViewedFolder.match(/^(?:(C|S|G)([0-9]+)|L)$/);
+ var select = 0;
+ if (matches) {
+ if (matches[1] == 'C') {
+ if (this._collectionRowMap[matches[2]]) {
+ select = this._collectionRowMap[matches[2]];
+ }
+ // Search recursively
+ else {
+ var path = [];
+ var failsafe = 10; // Only go up ten levels
+ var lastCol = matches[2];
+ do {
+ failsafe--;
+ var col = Zotero.Collections.get(lastCol);
+ if (!col) {
+ var msg = "Last-viewed collection not found";
+ Zotero.debug(msg);
+ path = [];
+ break;
+ }
+ var par = col.getParent();
+ if (!par) {
+ var msg = "Parent collection not found in "
+ + "Zotero.CollectionTreeView.setTree()";
+ Zotero.debug(msg, 1);
+ Components.utils.reportError(msg);
+ path = [];
+ break;
+ }
+ lastCol = par;
+ path.push(lastCol);
+ }
+ while (!this._collectionRowMap[lastCol] && failsafe > 0)
+ if (path.length) {
+ for (var i=path.length-1; i>=0; i--) {
+ var id = path[i];
+ var row = this._collectionRowMap[id];
+ if (!row) {
+ var msg = "Collection not found in tree in "
+ + "Zotero.CollectionTreeView.setTree()";
+ Zotero.debug(msg, 1);
+ Components.utils.reportError(msg);
+ break;
+ }
+ if (!this.isContainerOpen(row)) {
+ this.toggleOpenState(row);
+ if (this._collectionRowMap[matches[2]]) {
+ select = this._collectionRowMap[matches[2]];
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (matches[1] == 'S' && this._searchRowMap[matches[2]]) {
+ select = this._searchRowMap[matches[2]];
+ }
+ else if (matches[1] == 'G' && this._groupRowMap[matches[2]]) {
+ select = this._groupRowMap[matches[2]];
+ }
+ }
+
+ return select;
+}
+
/*
* Delete the selection
@@ -1790,6 +1828,7 @@ Zotero.ItemGroup.prototype.getChildItems = function()
Zotero.debug(e, 2);
throw (e);
}
+
return Zotero.Items.get(ids);
}
@@ -1826,7 +1865,7 @@ Zotero.ItemGroup.prototype.getSearchObject = function() {
s.addCondition('deleted', 'true');
}
else if (this.isSearch()) {
- s.id = this.ref.id;
+ var s = this.ref;
}
else {
throw ('Invalid search mode in Zotero.ItemGroup.getSearchObject()');
diff --git a/chrome/content/zotero/xpcom/search.js b/chrome/content/zotero/xpcom/search.js
index 177b4f987..8cf11642a 100644
--- a/chrome/content/zotero/xpcom/search.js
+++ b/chrome/content/zotero/xpcom/search.js
@@ -1015,6 +1015,11 @@ Zotero.Search.prototype._buildQuery = function(){
var includeChildren = this._conditions[i]['operator'] == 'true';
continue;
+ case 'unfiled':
+ this._conditions[i]['operator']
+ var unfiled = this._conditions[i]['operator'] == 'true';
+ continue;
+
// Search subfolders
case 'recursive':
var recursive = this._conditions[i]['operator']=='true';
@@ -1063,6 +1068,15 @@ Zotero.Search.prototype._buildQuery = function(){
+ "WHERE sourceItemID IS NOT NULL))";
}
+ if (unfiled) {
+ sql += " AND (itemID NOT IN (SELECT itemID FROM collectionItems) "
+ // Exclude children
+ + "AND itemID NOT IN "
+ + "(SELECT itemID FROM itemAttachments WHERE sourceItemID IS NOT NULL "
+ + "UNION SELECT itemID FROM itemNotes WHERE sourceItemID IS NOT NULL)"
+ + ")";
+ }
+
if (this._hasPrimaryConditions) {
sql += " AND ";
@@ -1753,6 +1767,14 @@ Zotero.SearchConditions = new function(){
}
},
+ {
+ name: 'unfiled',
+ operators: {
+ true: true,
+ false: true
+ }
+ },
+
{
name: 'includeParentsAndChildren',
operators: {
@@ -2071,7 +2093,6 @@ Zotero.SearchConditions = new function(){
special: true
},
-
{
name: 'fulltextContent',
operators: {
diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js
index fe713bc6b..55a171e4c 100644
--- a/chrome/content/zotero/zoteroPane.js
+++ b/chrome/content/zotero/zoteroPane.js
@@ -56,7 +56,6 @@ var ZoteroPane = new function()
this.itemSelected = itemSelected;
this.reindexItem = reindexItem;
this.duplicateSelectedItem = duplicateSelectedItem;
- this.deleteSelectedCollection = deleteSelectedCollection;
this.editSelectedCollection = editSelectedCollection;
this.copySelectedItemsToClipboard = copySelectedItemsToClipboard;
this.clearQuicksearch = clearQuicksearch;
@@ -714,6 +713,55 @@ var ZoteroPane = new function()
window.openDialog('chrome://zotero/content/searchDialog.xul','','chrome,modal',io);
}
+ this.setUnfiled = function (libraryID, show) {
+ try {
+ var ids = Zotero.Prefs.get('unfiledLibraries').split(',');
+ }
+ catch (e) {
+ var ids = [];
+ }
+
+ if (!libraryID) {
+ libraryID = 0;
+ }
+
+ var newids = [];
+ for each(var id in ids) {
+ id = parseInt(id);
+ if (isNaN(id)) {
+ continue;
+ }
+ // Remove current library if hiding
+ if (id == libraryID && !show) {
+ continue;
+ }
+ // Remove libraryIDs that no longer exist
+ if (id != 0 && !Zotero.Libraries.exists(id)) {
+ continue;
+ }
+ newids.push(id);
+ }
+
+ // Add the current library if it's not already set
+ if (show && newids.indexOf(libraryID) == -1) {
+ newids.push(libraryID);
+ }
+
+ newids.sort();
+
+ Zotero.Prefs.set('unfiledLibraries', newids.join());
+
+ if (show) {
+ // 'UNFILED' + '000' + libraryID
+ Zotero.Prefs.set('lastViewedFolder', 'S' + '8634533000' + libraryID);
+ }
+
+ this.collectionsView.refresh();
+
+ // Select new row
+ var row = this.collectionsView.getLastViewedRow();
+ this.collectionsView.selection.select(row);
+ }
this.openLookupWindow = function () {
if (!Zotero.stateCheck()) {
@@ -1306,17 +1354,20 @@ var ZoteroPane = new function()
}
}
- function deleteSelectedCollection()
- {
+ this.deleteSelectedCollection = function () {
+ // Remove virtual Unfiled search
+ var row = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
+ if (row.isSearch() && (row.ref.id + "").match(/^8634533000/)) { // 'UNFILED000'
+ this.setUnfiled(row.ref.libraryID, false);
+ return;
+ }
+
if (!this.canEdit()) {
this.displayCannotEditLibraryMessage();
return;
}
if (this.collectionsView.selection.count == 1) {
- var row =
- this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
-
if (row.isCollection())
{
if (confirm(Zotero.getString('pane.collections.delete')))
@@ -1797,16 +1848,17 @@ var ZoteroPane = new function()
newSavedSearch: 1,
newSubcollection: 2,
sep1: 3,
- editSelectedCollection: 4,
- removeCollection: 5,
- sep2: 6,
- exportCollection: 7,
- createBibCollection: 8,
- exportFile: 9,
- loadReport: 10,
- emptyTrash: 11,
- createCommonsBucket: 12,
- refreshCommonsBucket: 13
+ showUnfiled: 4,
+ editSelectedCollection: 5,
+ removeCollection: 6,
+ sep2: 7,
+ exportCollection: 8,
+ createBibCollection: 9,
+ exportFile: 10,
+ loadReport: 11,
+ emptyTrash: 12,
+ createCommonsBucket: 13,
+ refreshCommonsBucket: 14
};
var itemGroup = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex);
@@ -1846,14 +1898,27 @@ var ZoteroPane = new function()
}
// Saved Search
else if (itemGroup.isSearch()) {
- show = [
- m.editSelectedCollection,
- m.removeCollection,
- m.sep2,
- m.exportCollection,
- m.createBibCollection,
- m.loadReport
- ];
+ // Unfiled items view
+ if ((itemGroup.ref.id + "").match(/^8634533000/)) { // 'UNFILED000'
+ show = [
+ m.removeCollection
+ ];
+
+ menu.childNodes[m.removeCollection].setAttribute('label', Zotero.getString('general.remove'));
+ }
+ // Normal search view
+ else {
+ show = [
+ m.editSelectedCollection,
+ m.removeCollection,
+ m.sep2,
+ m.exportCollection,
+ m.createBibCollection,
+ m.loadReport
+ ];
+
+ menu.childNodes[m.removeCollection].setAttribute('label', Zotero.getString('pane.collections.menu.remove.savedSearch'));
+ }
var s = [m.exportCollection, m.createBibCollection, m.loadReport];
if (this.itemsView.rowCount>0) {
@@ -1865,7 +1930,6 @@ var ZoteroPane = new function()
// Adjust labels
menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch'));
- menu.childNodes[m.removeCollection].setAttribute('label', Zotero.getString('pane.collections.menu.remove.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'));
@@ -1884,12 +1948,12 @@ var ZoteroPane = new function()
}
// Group
else if (itemGroup.isGroup()) {
- show = [m.newCollection, m.newSavedSearch];
+ show = [m.newCollection, m.newSavedSearch, m.sep1, m.showUnfiled];
}
// Library
else
{
- show = [m.newCollection, m.newSavedSearch, m.sep1, m.exportFile];
+ show = [m.newCollection, m.newSavedSearch, m.sep1, m.showUnfiled, m.sep2, m.exportFile];
}
// Disable some actions if user doesn't have write access
diff --git a/chrome/content/zotero/zoteroPane.xul b/chrome/content/zotero/zoteroPane.xul
index 9fb37eccf..5dd8d9f60 100644
--- a/chrome/content/zotero/zoteroPane.xul
+++ b/chrome/content/zotero/zoteroPane.xul
@@ -216,6 +216,7 @@
+
diff --git a/chrome/locale/en-US/zotero/searchbox.dtd b/chrome/locale/en-US/zotero/searchbox.dtd
index 8f0843502..406f9be08 100644
--- a/chrome/locale/en-US/zotero/searchbox.dtd
+++ b/chrome/locale/en-US/zotero/searchbox.dtd
@@ -6,7 +6,7 @@
-
+
diff --git a/chrome/locale/en-US/zotero/zotero.dtd b/chrome/locale/en-US/zotero/zotero.dtd
index 4b57c0d53..d5562076d 100644
--- a/chrome/locale/en-US/zotero/zotero.dtd
+++ b/chrome/locale/en-US/zotero/zotero.dtd
@@ -37,6 +37,8 @@
+
+
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
index 0fa179c25..23934d134 100644
--- a/chrome/locale/en-US/zotero/zotero.properties
+++ b/chrome/locale/en-US/zotero/zotero.properties
@@ -33,6 +33,7 @@ general.create = Create
general.seeForMoreInformation = See %S for more information.
general.enable = Enable
general.disable = Disable
+general.remove = Remove
general.operationInProgress = A Zotero operation is currently in progress.
general.operationInProgress.waitUntilFinished = Please wait until it has finished.
@@ -108,6 +109,7 @@ pane.collections.rename = Rename collection:
pane.collections.library = My Library
pane.collections.trash = Trash
pane.collections.untitled = Untitled
+pane.collections.unfiled = Unfiled Items
pane.collections.menu.rename.collection = Rename Collection...
pane.collections.menu.edit.savedSearch = Edit Saved Search