Addresses #513, Deleted Items folder
Adds handling for parent/child items in trash -- non-deleted context items will appear in gray, and "Restore to Library" and the delete keystrokes won't be available if any of those are selected Like other search views, Select All will select only the deleted items
This commit is contained in:
parent
cb8e226ae9
commit
5e774efc42
5 changed files with 126 additions and 43 deletions
|
@ -819,6 +819,7 @@ var ZoteroPane = new function()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function itemSelected()
|
||||
{
|
||||
if (!Zotero.stateCheck()) {
|
||||
|
@ -829,7 +830,8 @@ var ZoteroPane = new function()
|
|||
// Display restore button if items selected in Trash
|
||||
if (this.itemsView && this.itemsView.selection.count) {
|
||||
document.getElementById('zotero-item-restore-button').hidden
|
||||
= !this.itemsView._itemGroup.isTrash();
|
||||
= !this.itemsView._itemGroup.isTrash()
|
||||
|| _nonDeletedItemsSelected(this.itemsView);
|
||||
}
|
||||
|
||||
var tabs = document.getElementById('zotero-view-tabs');
|
||||
|
@ -913,7 +915,27 @@ var ZoteroPane = new function()
|
|||
label.value = Zotero.getString('pane.item.selected.zero');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if any selected items in the passed (trash) treeview are not deleted
|
||||
*
|
||||
* @param {nsITreeView}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function _nonDeletedItemsSelected(itemsView) {
|
||||
var start = {};
|
||||
var end = {};
|
||||
for (var i=0, len=itemsView.selection.getRangeCount(); i<len; i++) {
|
||||
itemsView.selection.getRangeAt(i, start, end);
|
||||
for (var j=start.value; j<=end.value; j++) {
|
||||
if (!itemsView._getItemAtRow(j).ref.deleted) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -973,6 +995,19 @@ var ZoteroPane = new function()
|
|||
this.itemsView._itemGroup.isShare()) {
|
||||
return;
|
||||
}
|
||||
// Do nothing in trash view if any non-deleted items are selected
|
||||
else if (this.itemsView._itemGroup.isTrash()) {
|
||||
var start = {};
|
||||
var end = {};
|
||||
for (var i=0, len=this.itemsView.selection.getRangeCount(); i<len; i++) {
|
||||
this.itemsView.selection.getRangeAt(i, start, end);
|
||||
for (var j=start.value; j<=end.value; j++) {
|
||||
if (!this.itemsView._getItemAtRow(j).ref.deleted) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var eraseChildren = {value: true};
|
||||
|
@ -981,15 +1016,16 @@ var ZoteroPane = new function()
|
|||
var hasChildren;
|
||||
|
||||
if (!this.getSelectedCollection()) {
|
||||
var start = new Object();
|
||||
var end = new Object();
|
||||
var start = {};
|
||||
var end = {};
|
||||
for (var i=0, len=this.itemsView.selection.getRangeCount(); i<len; i++) {
|
||||
this.itemsView.selection.getRangeAt(i,start,end);
|
||||
for (var j=start.value; j<=end.value; j++)
|
||||
this.itemsView.selection.getRangeAt(i, start, end);
|
||||
for (var j=start.value; j<=end.value; j++) {
|
||||
if (this.itemsView._getItemAtRow(j).numChildren()) {
|
||||
hasChildren = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1170,8 +1170,7 @@ Zotero.ItemGroup.prototype.setTags = function(tags)
|
|||
* Returns TRUE if saved search, quicksearch or tag filter
|
||||
*/
|
||||
Zotero.ItemGroup.prototype.isSearchMode = function() {
|
||||
// Search
|
||||
if (this.isSearch()) {
|
||||
if (this.isSearch() || this.isTrash()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -269,13 +269,15 @@ Zotero.Item.prototype.loadPrimaryData = function(allowFail) {
|
|||
break;
|
||||
|
||||
case 'numNotes':
|
||||
colSQL = '(SELECT COUNT(*) FROM itemNotes '
|
||||
+ 'WHERE sourceItemID=I.itemID) AS numNotes';
|
||||
colSQL = '(SELECT COUNT(*) FROM itemNotes INo '
|
||||
+ 'WHERE sourceItemID=I.itemID AND INo.itemID '
|
||||
+ 'NOT IN (SELECT itemID FROM deletedItems)) AS numNotes';
|
||||
break;
|
||||
|
||||
case 'numAttachments':
|
||||
colSQL = '(SELECT COUNT(*) FROM itemAttachments '
|
||||
+ 'WHERE sourceItemID=I.itemID) AS numAttachments';
|
||||
colSQL = '(SELECT COUNT(*) FROM itemAttachments IA '
|
||||
+ 'WHERE sourceItemID=I.itemID AND IA.itemID '
|
||||
+ 'NOT IN (SELECT itemID FROM deletedItems)) AS numAttachments';
|
||||
break;
|
||||
}
|
||||
if (colSQL) {
|
||||
|
@ -326,7 +328,15 @@ Zotero.Item.prototype.loadFromRow = function(row, reload) {
|
|||
// Only accept primary field data through loadFromRow()
|
||||
if (this.isPrimaryField(col)) {
|
||||
//Zotero.debug("Setting field '" + col + "' to '" + row[col] + "' for item " + this.id);
|
||||
this['_' + col] = row[col] ? row[col] : '';
|
||||
switch (col) {
|
||||
case 'numNotes':
|
||||
case 'numAttachments':
|
||||
this['_' + col] = row[col] ? parseInt(row[col]) : 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
this['_' + col] = row[col] ? row[col] : '';
|
||||
}
|
||||
}
|
||||
else {
|
||||
Zotero.debug(col + ' is not a valid primary field');
|
||||
|
@ -1895,8 +1905,8 @@ Zotero.Item.prototype.isRegularItem = function() {
|
|||
}
|
||||
|
||||
|
||||
Zotero.Item.prototype.numChildren = function() {
|
||||
return this.numNotes() + this.numAttachments();
|
||||
Zotero.Item.prototype.numChildren = function(includeTrashed) {
|
||||
return this.numNotes(includeTrashed) + this.numAttachments(includeTrashed);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1996,9 +2006,12 @@ Zotero.Item.prototype.updateNote = function(text) {
|
|||
|
||||
|
||||
/**
|
||||
* Returns number of notes in item
|
||||
**/
|
||||
Zotero.Item.prototype.numNotes = function() {
|
||||
* Returns number of child notes of item
|
||||
*
|
||||
* @param {Boolean} includeTrashed Include trashed child items in count
|
||||
* @return {Integer}
|
||||
*/
|
||||
Zotero.Item.prototype.numNotes = function(includeTrashed) {
|
||||
if (this.isNote()) {
|
||||
throw ("numNotes() cannot be called on items of type 'note'");
|
||||
}
|
||||
|
@ -2007,7 +2020,14 @@ Zotero.Item.prototype.numNotes = function() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return this._numNotes;
|
||||
var deleted = 0;
|
||||
if (includeTrashed) {
|
||||
var sql = "SELECT COUNT(*) FROM itemNotes WHERE sourceItemID=? AND "
|
||||
+ "itemID IN (SELECT itemID FROM deletedItems)";
|
||||
deleted = parseInt(Zotero.DB.valueQuery(sql, this.id));
|
||||
}
|
||||
|
||||
return this._numNotes + deleted;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2121,9 +2141,12 @@ Zotero.Item.prototype.setNote = function(text) {
|
|||
|
||||
|
||||
/**
|
||||
* Returns an array of note itemIDs for this item
|
||||
**/
|
||||
Zotero.Item.prototype.getNotes = function() {
|
||||
* Returns child notes of this item
|
||||
*
|
||||
* @param {Boolean} includeTrashed Include trashed child items
|
||||
* @return {Integer[]} Array of itemIDs, or FALSE if none
|
||||
*/
|
||||
Zotero.Item.prototype.getNotes = function(includeTrashed) {
|
||||
if (this.isNote()) {
|
||||
throw ("getNotes() cannot be called on items of type 'note'");
|
||||
}
|
||||
|
@ -2134,6 +2157,9 @@ Zotero.Item.prototype.getNotes = function() {
|
|||
|
||||
var sql = "SELECT N.itemID, title FROM itemNotes N NATURAL JOIN items "
|
||||
+ "WHERE sourceItemID=?";
|
||||
if (!includeTrashed) {
|
||||
sql += " AND N.itemID NOT IN (SELECT itemID FROM deletedItems)";
|
||||
}
|
||||
|
||||
if (Zotero.Prefs.get('sortNotesChronologically')) {
|
||||
sql += " ORDER BY dateAdded";
|
||||
|
@ -2191,9 +2217,12 @@ Zotero.Item.prototype.isAttachment = function() {
|
|||
|
||||
|
||||
/**
|
||||
* Returns number of files in item
|
||||
**/
|
||||
Zotero.Item.prototype.numAttachments = function() {
|
||||
* Returns number of child attachments of item
|
||||
*
|
||||
* @param {Boolean} includeTrashed Include trashed child items in count
|
||||
* @return {Integer}
|
||||
*/
|
||||
Zotero.Item.prototype.numAttachments = function(includeTrashed) {
|
||||
if (this.isAttachment()) {
|
||||
throw ("numAttachments() cannot be called on attachment items");
|
||||
}
|
||||
|
@ -2202,7 +2231,14 @@ Zotero.Item.prototype.numAttachments = function() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
return this._numAttachments;
|
||||
var deleted = 0;
|
||||
if (includeTrashed) {
|
||||
var sql = "SELECT COUNT(*) FROM itemAttachments WHERE sourceItemID=? AND "
|
||||
+ "itemID IN (SELECT itemID FROM deletedItems)";
|
||||
deleted = parseInt(Zotero.DB.valueQuery(sql, this.id));
|
||||
}
|
||||
|
||||
return this._numAttachments + deleted;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2680,10 +2716,12 @@ Zotero.Item.prototype.__defineGetter__('attachmentModificationTime', function ()
|
|||
|
||||
|
||||
/**
|
||||
* Returns an array of attachment itemIDs that have this item as a source,
|
||||
* or FALSE if none
|
||||
**/
|
||||
Zotero.Item.prototype.getAttachments = function() {
|
||||
* Returns child attachments of this item
|
||||
*
|
||||
* @param {Boolean} includeTrashed Include trashed child items
|
||||
* @return {Integer[]} Array of itemIDs, or FALSE if none
|
||||
*/
|
||||
Zotero.Item.prototype.getAttachments = function(includeTrashed) {
|
||||
if (this.isAttachment()) {
|
||||
throw ("getAttachments() cannot be called on attachment items");
|
||||
}
|
||||
|
@ -2698,6 +2736,9 @@ Zotero.Item.prototype.getAttachments = function() {
|
|||
+ "LEFT JOIN itemDataValues IDV "
|
||||
+ "ON (ID.valueID=IDV.valueID) "
|
||||
+ "WHERE sourceItemID=?";
|
||||
if (!includeTrashed) {
|
||||
sql += " AND A.itemID NOT IN (SELECT itemID FROM deletedItems)";
|
||||
}
|
||||
|
||||
if (Zotero.Prefs.get('sortAttachmentsChronologically')) {
|
||||
sql += " ORDER BY dateAdded";
|
||||
|
|
|
@ -567,8 +567,10 @@ Zotero.Items = new function() {
|
|||
// Should be the same as parts in Zotero.Item.loadPrimaryData
|
||||
var sql = 'SELECT I.*, '
|
||||
+ getFirstCreatorSQL() + ', '
|
||||
+ "(SELECT COUNT(*) FROM itemNotes WHERE sourceItemID=I.itemID) AS numNotes, "
|
||||
+ "(SELECT COUNT(*) FROM itemAttachments WHERE sourceItemID=I.itemID) AS numAttachments "
|
||||
+ "(SELECT COUNT(*) FROM itemNotes INo WHERE sourceItemID=I.itemID AND "
|
||||
+ "INo.itemID NOT IN (SELECT itemID FROM deletedItems)) AS numNotes, "
|
||||
+ "(SELECT COUNT(*) FROM itemAttachments IA WHERE sourceItemID=I.itemID AND "
|
||||
+ "IA.itemID NOT IN (SELECT itemID FROM deletedItems)) AS numAttachments "
|
||||
+ 'FROM items I WHERE 1';
|
||||
if (arguments[0]) {
|
||||
sql += ' AND I.itemID IN (' + Zotero.join(arguments[0], ',') + ')';
|
||||
|
|
|
@ -586,7 +586,7 @@ Zotero.ItemTreeView.prototype.getCellText = function(row, column)
|
|||
|
||||
if(column.id == "zotero-items-column-numChildren")
|
||||
{
|
||||
var c = obj.numChildren();
|
||||
var c = obj.numChildren(this._itemGroup.isTrash());
|
||||
// Don't display '0'
|
||||
if(c && parseInt(c) > 0) {
|
||||
val = c;
|
||||
|
@ -668,7 +668,9 @@ Zotero.ItemTreeView.prototype.isContainerEmpty = function(row)
|
|||
if(this._sourcesOnly) {
|
||||
return true;
|
||||
} else {
|
||||
return (this._getItemAtRow(row).numNotes() == 0 && this._getItemAtRow(row).numAttachments() == 0);
|
||||
var includeTrashed = this._itemGroup.isTrash();
|
||||
return (this._getItemAtRow(row).numNotes(includeTrashed) == 0
|
||||
&& this._getItemAtRow(row).numAttachments(includeTrashed) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -727,8 +729,9 @@ Zotero.ItemTreeView.prototype.toggleOpenState = function(row, skipItemMapRefresh
|
|||
else {
|
||||
var item = this._getItemAtRow(row).ref;
|
||||
//Get children
|
||||
var attachments = item.getAttachments();
|
||||
var notes = item.getNotes();
|
||||
var includeTrashed = this._itemGroup.isTrash();
|
||||
var attachments = item.getAttachments(includeTrashed);
|
||||
var notes = item.getNotes(includeTrashed);
|
||||
|
||||
var newRows;
|
||||
if(attachments && notes)
|
||||
|
@ -891,6 +894,8 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
|
|||
return field;
|
||||
}
|
||||
|
||||
var includeTrashed = this._itemGroup.isTrash();
|
||||
|
||||
function rowSort(a,b) {
|
||||
var cmp, fieldA, fieldB;
|
||||
|
||||
|
@ -915,7 +920,7 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
|
|||
break;
|
||||
|
||||
case 'numChildren':
|
||||
cmp = b.numChildren() - a.numChildren();
|
||||
cmp = b.numChildren(includeTrashed) - a.numChildren(includeTrashed);
|
||||
if (cmp) {
|
||||
return cmp;
|
||||
}
|
||||
|
@ -2273,26 +2278,26 @@ Zotero.ItemTreeView.TreeRow.prototype.getField = function(field, unformatted)
|
|||
return this.ref.getField(field, unformatted, true);
|
||||
}
|
||||
|
||||
Zotero.ItemTreeView.TreeRow.prototype.numChildren = function()
|
||||
Zotero.ItemTreeView.TreeRow.prototype.numChildren = function(includeTrashed)
|
||||
{
|
||||
if(this.ref.isRegularItem())
|
||||
return this.ref.numChildren();
|
||||
return this.ref.numChildren(includeTrashed);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Zotero.ItemTreeView.TreeRow.prototype.numNotes = function()
|
||||
Zotero.ItemTreeView.TreeRow.prototype.numNotes = function(includeTrashed)
|
||||
{
|
||||
if(this.ref.isRegularItem())
|
||||
return this.ref.numNotes();
|
||||
return this.ref.numNotes(includeTrashed);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Zotero.ItemTreeView.TreeRow.prototype.numAttachments = function()
|
||||
Zotero.ItemTreeView.TreeRow.prototype.numAttachments = function(includeTrashed)
|
||||
{
|
||||
if(this.ref.isRegularItem())
|
||||
return this.ref.numAttachments();
|
||||
return this.ref.numAttachments(includeTrashed);
|
||||
else
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue