find duplicates

This commit is contained in:
Damien Elmes 2012-05-27 00:11:59 +09:00
parent 975ad62019
commit cf3b51c30c
2 changed files with 45 additions and 84 deletions

View file

@ -2,7 +2,7 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import sre_constants import sre_constants, cgi
from aqt.qt import * from aqt.qt import *
import time, types, sys, re import time, types, sys, re
from operator import attrgetter, itemgetter from operator import attrgetter, itemgetter
@ -1140,73 +1140,45 @@ update cards set usn=?, mod=?, did=? where odid=0 and id in """ + ids2str(
###################################################################### ######################################################################
def onFindDupes(self): def onFindDupes(self):
return showInfo("not yet implemented") d = QDialog(self)
win = QDialog(self) frm = aqt.forms.finddupes.Ui_Dialog()
aqt = ankiqt.forms.finddupes.Ui_Dialog() frm.setupUi(d)
dialog.setupUi(win) restoreGeom(d, "findDupes")
restoreGeom(win, "findDupes") fields = sorted(anki.find.fieldNames(self.col, downcase=False))
fields = sorted(self.card.note.model.fieldModels, key=attrgetter("name")) frm.fields.addItems(fields)
# per-model data
data = self.col.db.all("""
select fm.id, m.name || '>' || fm.name from fieldmodels fm, models m
where fm.modelId = m.id""")
data.sort(key=itemgetter(1))
# all-model data
data2 = self.col.db.all("""
select fm.id, fm.name from fieldmodels fm""")
byName = {}
for d in data2:
if d[1] in byName:
byName[d[1]].append(d[0])
else:
byName[d[1]] = [d[0]]
names = byName.keys()
names.sort()
alldata = [(byName[n], n) for n in names] + data
dialog.searchArea.addItems([d[1] for d in alldata])
# links # links
dialog.webView.page().setLinkDelegationPolicy( frm.webView.page().setLinkDelegationPolicy(
QWebPage.DelegateAllLinks) QWebPage.DelegateAllLinks)
self.connect(dialog.webView, self.connect(frm.webView,
SIGNAL("linkClicked(QUrl)"), SIGNAL("linkClicked(QUrl)"),
self.dupeLinkClicked) self.dupeLinkClicked)
def onFin(code): def onFin(code):
saveGeom(win, "findDupes") saveGeom(d, "findDupes")
self.connect(win, SIGNAL("finished(int)"), onFin) self.connect(d, SIGNAL("finished(int)"), onFin)
def onClick(): def onClick():
idx = dialog.searchArea.currentIndex() field = fields[frm.fields.currentIndex()]
data = alldata[idx] self.duplicatesReport(frm.webView, field, frm.search.text())
if isinstance(data[0], list): search = frm.buttonBox.addButton(
# all models _("Search"), QDialogButtonBox.ActionRole)
fmids = data[0] self.connect(search, SIGNAL("clicked()"), onClick)
else: d.show()
# single model
fmids = [data[0]]
self.duplicatesReport(dialog.webView, fmids)
self.connect(dialog.searchButton, SIGNAL("clicked()"), def duplicatesReport(self, web, fname, search):
onClick) self.mw.progress.start()
win.show() res = self.mw.col.findDupes(fname, search)
def duplicatesReport(self, web, fmids):
self.col.startProgress(2)
self.col.updateProgress(_("Finding..."))
res = self.col.findDuplicates(fmids)
t = "<html><body>" t = "<html><body>"
t += _("Duplicate Groups: %d") % len(res) t += _("Found %d duplicates in %d notes.") % (
sum(len(r[1]) for r in res), len(res))
t += "<p><ol>" t += "<p><ol>"
for val, nids in res:
for group in res: t += '<li><a href="%s">%s</a>: %s</a>' % (
t += '<li><a href="%s">%s</a>' % ( "nid:" + ",".join(str(id) for id in nids),
"nid:" + ",".join(str(id) for id in group[1]), _("%d notes") % len(nids),
group[0]) cgi.escape(val))
t += "</ol>" t += "</ol>"
t += "</body></html>" t += "</body></html>"
web.setHtml(t) web.setHtml(t)
self.col.finishProgress() self.mw.progress.finish()
def dupeLinkClicked(self, link): def dupeLinkClicked(self, link):
self.form.searchEdit.lineEdit().setText(link.toString()) self.form.searchEdit.lineEdit().setText(link.toString())

View file

@ -6,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>531</width>
<height>300</height> <height>345</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -16,35 +16,25 @@
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="1"> <item row="1" column="2" colspan="2">
<widget class="QComboBox" name="fields"/>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Optional limit:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Find Duplicates in:</string> <string>Look in field:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2"> <item row="2" column="2" colspan="2">
<widget class="QComboBox" name="searchArea"/> <widget class="QLineEdit" name="search"/>
</item>
<item row="0" column="4">
<widget class="QPushButton" name="searchButton">
<property name="text">
<string>&amp;Search</string>
</property>
</widget>
</item>
<item row="0" column="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item> </item>
</layout> </layout>
</item> </item>
@ -92,8 +82,7 @@
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>searchArea</tabstop> <tabstop>fields</tabstop>
<tabstop>searchButton</tabstop>
<tabstop>webView</tabstop> <tabstop>webView</tabstop>
<tabstop>buttonBox</tabstop> <tabstop>buttonBox</tabstop>
</tabstops> </tabstops>