mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
find duplicates
This commit is contained in:
parent
975ad62019
commit
cf3b51c30c
2 changed files with 45 additions and 84 deletions
|
@ -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())
|
||||||
|
|
|
@ -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>&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>
|
||||||
|
|
Loading…
Reference in a new issue