www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

commit 0746824c0f0311f042b3779b73e931575602cb9b
parent 18c1287dd5716b49a4d3d41a5a0da3a6a766d6b2
Author: Dan Stillman <dstillman@zotero.org>
Date:   Fri,  6 Mar 2009 21:44:47 +0000

Addresses #1146, Check for duplicate items functionality

Ben's duplicate detection code, with the integration reworked a bit

Very rough, so currently requires creation of a boolean extensions.zotero.debugShowDuplicates pref to view the Actions menu option


Diffstat:
Mchrome/content/zotero/overlay.js | 24+++++++++++++++++++++++-
Mchrome/content/zotero/overlay.xul | 2++
Mchrome/content/zotero/xpcom/collectionTreeView.js | 12+++++++++++-
Achrome/content/zotero/xpcom/duplicate.js | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mchrome/locale/en-US/zotero/zotero.dtd | 1+
5 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/chrome/content/zotero/overlay.js b/chrome/content/zotero/overlay.js @@ -225,6 +225,10 @@ var ZoteroPane = new function() sep.nextSibling.nextSibling.nextSibling.hidden = false; sep.nextSibling.nextSibling.nextSibling.nextSibling.hidden = false; } + + if (Zotero.Prefs.get('debugShowDuplicates')) { + document.getElementById('zotero-tb-actions-showDuplicates').hidden = false; + } } @@ -796,6 +800,7 @@ var ZoteroPane = new function() var itemgroup = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex); itemgroup.setSearch(''); itemgroup.setTags(getTagSelection()); + itemgroup.showDuplicates = false; try { Zotero.UnresponsiveScriptIndicator.disable(); @@ -825,6 +830,23 @@ var ZoteroPane = new function() } + + this.showDuplicates = function () { + if (this.collectionsView.selection.count == 1 && this.collectionsView.selection.currentIndex != -1) { + var itemGroup = this.collectionsView._getItemAtRow(this.collectionsView.selection.currentIndex); + itemGroup.showDuplicates = true; + + try { + Zotero.UnresponsiveScriptIndicator.disable(); + this.itemsView.refresh(); + } + finally { + Zotero.UnresponsiveScriptIndicator.enable(); + } + } + } + + function itemSelected() { if (!Zotero.stateCheck()) { @@ -998,7 +1020,7 @@ var ZoteroPane = new function() if (this.itemsView._itemGroup.isCollection()) { var noPrompt = true; } - // Do nothing in search view + // Do nothing in search and share views else if (this.itemsView._itemGroup.isSearch() || this.itemsView._itemGroup.isShare()) { return; diff --git a/chrome/content/zotero/overlay.xul b/chrome/content/zotero/overlay.xul @@ -128,6 +128,8 @@ label="Search for Shared Libraries" oncommand="Zotero.Zeroconf.findInstances()"/> <menuseparator id="zotero-tb-actions-plugins-separator"/> <menuitem id="zotero-tb-actions-timeline" label="&zotero.toolbar.timeline.label;" oncommand="Zotero_Timeline_Interface.loadTimeline()"/> + <!-- TODO: localize <menuitem id="zotero-tb-actions-duplicate" label="&zotero.toolbar.duplicate.label;" oncommand="ZoteroPane.showDuplicates()"/>--> + <menuitem id="zotero-tb-actions-showDuplicates" label="Show Duplicates" oncommand="ZoteroPane.showDuplicates()" hidden="true"/> <menuseparator id="zotero-tb-actions-sync-separator"/> <menuitem hidden="true" label="Sync Debugging" disabled="true"/> <menuitem hidden="true" label=" Clear Server Data" oncommand="Zotero.Sync.Server.clear()"/> diff --git a/chrome/content/zotero/xpcom/collectionTreeView.js b/chrome/content/zotero/xpcom/collectionTreeView.js @@ -37,6 +37,7 @@ Zotero.CollectionTreeView = function() this.itemToSelect = null; this._highlightedRows = {}; this._unregisterID = Zotero.Notifier.registerObserver(this, ['collection', 'search', 'share']); + this.showDuplicates = false; } /* @@ -1095,7 +1096,16 @@ Zotero.ItemGroup.prototype.getChildItems = function() var s = this.getSearchObject(); try { - var ids = s.search(); + var ids; + if (this.showDuplicates) { + var duplicates = new Zotero.Duplicate; + var tmpTable = s.search(true); + ids = duplicates.getIDs(tmpTable); + Zotero.DB.query("DROP TABLE " + tmpTable); + } + else { + ids = s.search(); + } } catch (e) { Zotero.DB.rollbackAllTransactions(); diff --git a/chrome/content/zotero/xpcom/duplicate.js b/chrome/content/zotero/xpcom/duplicate.js @@ -0,0 +1,83 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright (c) 2006 Center for History and New Media + George Mason University, Fairfax, Virginia, USA + http://chnm.gmu.edu + + Licensed under the Educational Community License, Version 1.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.opensource.org/licenses/ecl1.php + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + ***** END LICENSE BLOCK ***** +*/ + +Zotero.Duplicate = function(duplicateID) { + this._id = duplicateID ? duplicateID : null; + this._itemIDs = []; +} + +Zotero.Duplicate.prototype.__defineGetter__('id', function () { return this._id; }); + +Zotero.Duplicate.prototype.getIDs = function(idsTable) { + if (!idsTable) { + return; + } + + var minLen = 5, percentLen = 1./3, checkLen, i, j; + + var sql = "SELECT itemID, value AS val " + + "FROM " + idsTable + " NATURAL JOIN itemData " + + "NATURAL JOIN itemDataValues " + + "WHERE fieldID BETWEEN 110 AND 113 AND " + + "itemID NOT IN (SELECT itemID FROM itemAttachments) " + + "ORDER BY val"; + + var results = Zotero.DB.query(sql); + + var resultsLen = results.length; + this._itemIDs = []; + + for (i = 0; i < resultsLen; i++) { + results[i].len = results[i].val.length; + } + + for (i = 0; i < resultsLen; i++) { + // title must be at least minLen long to be a duplicate + if (results[i].len < minLen) { + continue; + } + + for (j = i + 1; j < resultsLen; j++) { + // duplicates must match the first checkLen characters + // checkLen = percentLen * the length of the longer title + checkLen = (results[i].len >= results[j].len) ? + parseInt(percentLen * results[i].len) : parseInt(percentLen * results[j].len); + checkLen = (checkLen > results[i].len) ? results[i].len : checkLen; + checkLen = (checkLen > results[j].len) ? results[j].len : checkLen; + checkLen = (checkLen < minLen) ? minLen : checkLen; + + if (results[i].val.substr(0, checkLen) == results[j].val.substr(0, checkLen)) { + // include results[i] when a duplicate is first found + if (j == i + 1) { + this._itemIDs.push(results[i].itemID); + } + this._itemIDs.push(results[j].itemID); + } + else { + break; + } + } + i = j - 1; + } + + return this._itemIDs; +} diff --git a/chrome/locale/en-US/zotero/zotero.dtd b/chrome/locale/en-US/zotero/zotero.dtd @@ -67,6 +67,7 @@ <!ENTITY zotero.toolbar.import.label "Import..."> <!ENTITY zotero.toolbar.export.label "Export Library..."> <!ENTITY zotero.toolbar.timeline.label "Create Timeline"> +<!ENTITY zotero.toolbar.duplicate.label "Show Duplicates"> <!ENTITY zotero.toolbar.preferences.label "Preferences..."> <!ENTITY zotero.toolbar.documentation.label "Documentation"> <!ENTITY zotero.toolbar.about.label "About Zotero">