added find duplicate tool to the browser

This commit is contained in:
Damien Elmes 2010-11-26 03:46:49 +09:00
parent 7d799d8b57
commit 1be2176b8e
3 changed files with 219 additions and 1 deletions

View file

@ -5,8 +5,9 @@
import sre_constants import sre_constants
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtWebKit import QWebPage
import time, types, sys, re import time, types, sys, re
from operator import attrgetter from operator import attrgetter, itemgetter
import anki, anki.utils, ankiqt.forms import anki, anki.utils, ankiqt.forms
from ankiqt import ui from ankiqt import ui
from anki.cards import cardsTable, Card from anki.cards import cardsTable, Card
@ -703,6 +704,7 @@ class EditDeck(QMainWindow):
self.connect(self.dialog.actionInvertSelection, SIGNAL("triggered()"), self.invertSelection) self.connect(self.dialog.actionInvertSelection, SIGNAL("triggered()"), self.invertSelection)
self.connect(self.dialog.actionSelectFacts, SIGNAL("triggered()"), self.selectFacts) self.connect(self.dialog.actionSelectFacts, SIGNAL("triggered()"), self.selectFacts)
self.connect(self.dialog.actionFindReplace, SIGNAL("triggered()"), self.onFindReplace) self.connect(self.dialog.actionFindReplace, SIGNAL("triggered()"), self.onFindReplace)
self.connect(self.dialog.actionFindDuplicates, SIGNAL("triggered()"), self.onFindDupes)
# jumps # jumps
self.connect(self.dialog.actionFirstCard, SIGNAL("triggered()"), self.onFirstCard) self.connect(self.dialog.actionFirstCard, SIGNAL("triggered()"), self.onFirstCard)
self.connect(self.dialog.actionLastCard, SIGNAL("triggered()"), self.onLastCard) self.connect(self.dialog.actionLastCard, SIGNAL("triggered()"), self.onLastCard)
@ -1126,6 +1128,81 @@ where id in %s""" % ids2str(sf))
def onFindReplaceHelp(self): def onFindReplaceHelp(self):
QDesktopServices.openUrl(QUrl(ankiqt.appWiki + QDesktopServices.openUrl(QUrl(ankiqt.appWiki +
"Browser#FindReplace")) "Browser#FindReplace"))
# Edit: finding dupes
######################################################################
def onFindDupes(self):
win = QDialog(self)
dialog = ankiqt.forms.finddupes.Ui_Dialog()
dialog.setupUi(win)
restoreGeom(win, "findDupes")
fields = sorted(self.currentCard.fact.model.fieldModels, key=attrgetter("name"))
# per-model data
data = self.deck.s.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.deck.s.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(QStringList([d[1] for d in alldata]))
# links
dialog.webView.page().setLinkDelegationPolicy(
QWebPage.DelegateAllLinks)
self.connect(dialog.webView,
SIGNAL("linkClicked(QUrl)"),
self.dupeLinkClicked)
def onFin(code):
saveGeom(win, "findDupes")
self.connect(win, SIGNAL("finished(int)"), onFin)
def onClick():
idx = dialog.searchArea.currentIndex()
data = alldata[idx]
if isinstance(data[0], list):
# all models
fmids = data[0]
else:
# single model
fmids = [data[0]]
self.duplicatesReport(dialog.webView, fmids)
self.connect(dialog.searchButton, SIGNAL("clicked()"),
onClick)
win.show()
def duplicatesReport(self, web, fmids):
self.deck.startProgress(2)
self.deck.updateProgress(_("Finding..."))
res = self.deck.findDuplicates(fmids)
t = "<html><body>"
t += _("Duplicate Groups: %d") % len(res)
t += "<p><ol>"
for group in res:
t += '<li><a href="%s">%s</a>' % (
"fid:" + ",".join(str(id) for id in group[1]),
group[0])
t += "</ol>"
t += "</body></html>"
web.setHtml(t)
self.deck.finishProgress()
def dupeLinkClicked(self, link):
self.dialog.filterEdit.setText(str(link.toString()))
self.updateSearch()
self.onFact()
# Jumping # Jumping
###################################################################### ######################################################################

View file

@ -226,6 +226,7 @@
<addaction name="actionInvertSelection"/> <addaction name="actionInvertSelection"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionFindReplace"/> <addaction name="actionFindReplace"/>
<addaction name="actionFindDuplicates"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionFont"/> <addaction name="actionFont"/>
</widget> </widget>
@ -585,6 +586,11 @@
<string>Ctrl+L</string> <string>Ctrl+L</string>
</property> </property>
</action> </action>
<action name="actionFindDuplicates">
<property name="text">
<string>Find &amp;Duplicates...</string>
</property>
</action>
</widget> </widget>
<resources> <resources>
<include location="../icons.qrc"/> <include location="../icons.qrc"/>

135
designer/finddupes.ui Normal file
View file

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Find Duplicates</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Find Duplicates in:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="searchArea"/>
</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>
</layout>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QWebView" name="webView">
<property name="url">
<url>
<string>about:blank</string>
</url>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QWebView</class>
<extends>QWidget</extends>
<header>QtWebKit/QWebView</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>searchArea</tabstop>
<tabstop>searchButton</tabstop>
<tabstop>webView</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>