move "find duplicates" into separate file

As far as I'm aware, no add-ons were extending that screen, so I've
dropped the old context object and the export in browser/__init__.py
This commit is contained in:
Damien Elmes 2021-05-08 14:32:15 +10:00
parent 220e14bf0f
commit 78a3536bfc
4 changed files with 139 additions and 123 deletions

View file

@ -7,7 +7,7 @@ import sys
import aqt
from .browser import Browser
from .dialogs import CardInfoDialog, ChangeModel, FindAndReplaceDialog, FindDupesDialog
from .dialogs import CardInfoDialog, ChangeModel, FindAndReplaceDialog
from .previewer import BrowserPreviewer, MultiCardPreviewer, Previewer
from .sidebar import (
SidebarItem,

View file

@ -3,8 +3,7 @@
from __future__ import annotations
import html
from typing import Any, Callable, List, Optional, Sequence, Tuple, Union
from typing import Callable, Optional, Sequence, Tuple, Union
import aqt
import aqt.forms
@ -18,19 +17,13 @@ from anki.stats import CardStats
from anki.tags import MARKED_TAG
from anki.utils import ids2str, isMac
from aqt import AnkiQt, gui_hooks
from aqt.browser.dialogs import (
CardInfoDialog,
ChangeModel,
FindAndReplaceDialog,
FindDupesDialog,
)
from aqt.browser.dialogs import CardInfoDialog, ChangeModel, FindAndReplaceDialog
from aqt.browser.previewer import BrowserPreviewer as PreviewDialog
from aqt.browser.previewer import Previewer
from aqt.browser.sidebar import SidebarTreeView
from aqt.browser.table import Table
from aqt.editor import Editor
from aqt.exporting import ExportDialog
from aqt.main import ResetReason
from aqt.operations.card import set_card_deck, set_card_flag
from aqt.operations.collection import undo
from aqt.operations.note import remove_notes
@ -52,26 +45,20 @@ from aqt.utils import (
HelpPage,
KeyboardModifiersPressed,
current_top_level_widget,
disable_help_button,
ensure_editor_saved,
getTag,
no_arg_trigger,
openHelp,
qtMenuShortcutWorkaround,
restore_combo_history,
restore_combo_index_for_session,
restoreGeom,
restoreSplitter,
restoreState,
save_combo_history,
save_combo_index_for_session,
saveGeom,
saveSplitter,
saveState,
showInfo,
showWarning,
skip_if_selection_is_empty,
tooltip,
tr,
)
from aqt.webview import AnkiWebView
@ -864,107 +851,9 @@ where id in %s"""
@no_arg_trigger
@ensure_editor_saved
def onFindDupes(self) -> None:
import anki.find
from aqt.browser.find_duplicates import FindDuplicatesDialog
d = QDialog(self)
self.mw.garbage_collect_on_dialog_finish(d)
frm = aqt.forms.finddupes.Ui_Dialog()
frm.setupUi(d)
restoreGeom(d, "findDupes")
disable_help_button(d)
searchHistory = restore_combo_history(frm.search, "findDupesFind")
fields = sorted(
anki.find.fieldNames(self.col, downcase=False), key=lambda x: x.lower()
)
frm.fields.addItems(fields)
restore_combo_index_for_session(frm.fields, fields, "findDupesFields")
self._dupesButton: Optional[QPushButton] = None
# links
frm.webView.set_title("find duplicates")
web_context = FindDupesDialog(dialog=d, browser=self)
frm.webView.set_bridge_command(self.dupeLinkClicked, web_context)
frm.webView.stdHtml("", context=web_context)
def onFin(code: Any) -> None:
saveGeom(d, "findDupes")
qconnect(d.finished, onFin)
def onClick() -> None:
search_text = save_combo_history(frm.search, searchHistory, "findDupesFind")
save_combo_index_for_session(frm.fields, "findDupesFields")
field = fields[frm.fields.currentIndex()]
self.duplicatesReport(frm.webView, field, search_text, frm, web_context)
search = frm.buttonBox.addButton(
tr.actions_search(), QDialogButtonBox.ActionRole
)
qconnect(search.clicked, onClick)
d.show()
def duplicatesReport(
self,
web: AnkiWebView,
fname: str,
search: str,
frm: aqt.forms.finddupes.Ui_Dialog,
web_context: FindDupesDialog,
) -> None:
self.mw.progress.start()
try:
res = self.mw.col.findDupes(fname, search)
except Exception as e:
self.mw.progress.finish()
showWarning(str(e))
return
if not self._dupesButton:
self._dupesButton = b = frm.buttonBox.addButton(
tr.browsing_tag_duplicates(), QDialogButtonBox.ActionRole
)
qconnect(b.clicked, lambda: self._onTagDupes(res))
t = ""
groups = len(res)
notes = sum(len(r[1]) for r in res)
part1 = tr.browsing_group(count=groups)
part2 = tr.browsing_note_count(count=notes)
t += tr.browsing_found_as_across_bs(part=part1, whole=part2)
t += "<p><ol>"
for val, nids in res:
t += (
"""<li><a href=# onclick="pycmd('%s');return false;">%s</a>: %s</a>"""
% (
html.escape(
self.col.build_search_string(
SearchNode(nids=SearchNode.IdList(ids=nids))
)
),
tr.browsing_note_count(count=len(nids)),
html.escape(val),
)
)
t += "</ol>"
web.stdHtml(t, context=web_context)
self.mw.progress.finish()
def _onTagDupes(self, res: List[Any]) -> None:
if not res:
return
self.begin_reset()
self.mw.checkpoint(tr.browsing_tag_duplicates())
nids = set()
for _, nidlist in res:
nids.update(nidlist)
self.col.tags.bulk_add(list(nids), tr.browsing_duplicate())
self.mw.progress.finish()
self.end_reset()
self.mw.requireReset(reason=ResetReason.BrowserTagDupes, context=self)
tooltip(tr.browsing_notes_tagged())
def dupeLinkClicked(self, link: str) -> None:
self.search_for(link)
self.onNote()
FindDuplicatesDialog(browser=self, mw=self.mw)
# Jumping
######################################################################

View file

@ -3,7 +3,6 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Dict, List, Optional, Sequence
import aqt
@ -32,12 +31,6 @@ from aqt.utils import (
)
@dataclass
class FindDupesDialog:
dialog: QDialog
browser: aqt.browser.Browser
class ChangeModel(QDialog):
def __init__(self, browser: aqt.browser.Browser, nids: Sequence[NoteId]) -> None:
QDialog.__init__(self, browser)

View file

@ -0,0 +1,134 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
import html
from typing import Any, List, Optional
import anki
import anki.find
import aqt
from anki.collection import SearchNode
from aqt.qt import *
from ..main import ResetReason
from ..utils import (
disable_help_button,
restore_combo_history,
restore_combo_index_for_session,
restoreGeom,
save_combo_history,
save_combo_index_for_session,
saveGeom,
showWarning,
tooltip,
tr,
)
from ..webview import AnkiWebView
from . import Browser
class FindDuplicatesDialog(QDialog):
def __init__(self, browser: Browser, mw: aqt.AnkiQt):
super().__init__(parent=browser)
self.browser = browser
self.mw = mw
self.mw.garbage_collect_on_dialog_finish(self)
form = aqt.forms.finddupes.Ui_Dialog()
form.setupUi(self)
restoreGeom(self, "findDupes")
disable_help_button(self)
searchHistory = restore_combo_history(form.search, "findDupesFind")
fields = sorted(
anki.find.fieldNames(self.mw.col, downcase=False), key=lambda x: x.lower()
)
form.fields.addItems(fields)
restore_combo_index_for_session(form.fields, fields, "findDupesFields")
self._dupesButton: Optional[QPushButton] = None
# links
form.webView.set_title("find duplicates")
form.webView.set_bridge_command(self.dupeLinkClicked, context=self)
form.webView.stdHtml("", context=self)
def onFin(code: Any) -> None:
saveGeom(self, "findDupes")
qconnect(self.finished, onFin)
def onClick() -> None:
search_text = save_combo_history(
form.search, searchHistory, "findDupesFind"
)
save_combo_index_for_session(form.fields, "findDupesFields")
field = fields[form.fields.currentIndex()]
self.duplicatesReport(form.webView, field, search_text, form)
search = form.buttonBox.addButton(
tr.actions_search(), QDialogButtonBox.ActionRole
)
qconnect(search.clicked, onClick)
self.show()
def duplicatesReport(
self,
web: AnkiWebView,
fname: str,
search: str,
frm: aqt.forms.finddupes.Ui_Dialog,
) -> None:
self.mw.progress.start()
try:
res = self.mw.col.findDupes(fname, search)
except Exception as e:
self.mw.progress.finish()
showWarning(str(e))
return
if not self._dupesButton:
self._dupesButton = b = frm.buttonBox.addButton(
tr.browsing_tag_duplicates(), QDialogButtonBox.ActionRole
)
qconnect(b.clicked, lambda: self._onTagDupes(res))
t = ""
groups = len(res)
notes = sum(len(r[1]) for r in res)
part1 = tr.browsing_group(count=groups)
part2 = tr.browsing_note_count(count=notes)
t += tr.browsing_found_as_across_bs(part=part1, whole=part2)
t += "<p><ol>"
for val, nids in res:
t += (
"""<li><a href=# onclick="pycmd('%s');return false;">%s</a>: %s</a>"""
% (
html.escape(
self.mw.col.build_search_string(
SearchNode(nids=SearchNode.IdList(ids=nids))
)
),
tr.browsing_note_count(count=len(nids)),
html.escape(val),
)
)
t += "</ol>"
web.stdHtml(t, context=self)
self.mw.progress.finish()
def _onTagDupes(self, res: List[Any]) -> None:
if not res:
return
self.browser.begin_reset()
self.mw.checkpoint(tr.browsing_tag_duplicates())
nids = set()
for _, nidlist in res:
nids.update(nidlist)
self.mw.col.tags.bulk_add(list(nids), tr.browsing_duplicate())
self.mw.progress.finish()
self.browser.end_reset()
self.mw.requireReset(reason=ResetReason.BrowserTagDupes, context=self)
tooltip(tr.browsing_notes_tagged())
def dupeLinkClicked(self, link: str) -> None:
self.browser.search_for(link)
self.browser.onNote()