# 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, Tuple import anki import anki.find import aqt from anki.collection import SearchNode from anki.notes import NoteId from aqt.qt import * from ..operations import QueryOp from ..operations.tag import add_tags_to_notes from ..utils import ( disable_help_button, restore_combo_history, restore_combo_index_for_session, restoreGeom, save_combo_history, save_combo_index_for_session, saveGeom, tr, ) 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) self.form = 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._on_duplicate_clicked, context=self) form.webView.stdHtml("", context=self) def on_finished(code: Any) -> None: saveGeom(self, "findDupes") qconnect(self.finished, on_finished) def on_click() -> None: search_text = save_combo_history( form.search, searchHistory, "findDupesFind" ) save_combo_index_for_session(form.fields, "findDupesFields") field = fields[form.fields.currentIndex()] QueryOp( parent=self.browser, op=lambda col: col.find_dupes(field, search_text), success=self.show_duplicates_report, ).run_in_background() search = form.buttonBox.addButton( tr.actions_search(), QDialogButtonBox.ActionRole ) qconnect(search.clicked, on_click) self.show() def show_duplicates_report(self, dupes: List[Tuple[str, List[NoteId]]]) -> None: if not self._dupesButton: self._dupesButton = b = self.form.buttonBox.addButton( tr.browsing_tag_duplicates(), QDialogButtonBox.ActionRole ) qconnect(b.clicked, lambda: self._tag_duplicates(dupes)) text = "" groups = len(dupes) notes = sum(len(r[1]) for r in dupes) part1 = tr.browsing_group(count=groups) part2 = tr.browsing_note_count(count=notes) text += tr.browsing_found_as_across_bs(part=part1, whole=part2) text += "

    " for val, nids in dupes: text += ( """
  1. %s: %s""" % ( html.escape( self.mw.col.build_search_string( SearchNode(nids=SearchNode.IdList(ids=nids)) ) ), tr.browsing_note_count(count=len(nids)), html.escape(val), ) ) text += "
" self.form.webView.stdHtml(text, context=self) def _tag_duplicates(self, dupes: List[Tuple[str, List[NoteId]]]) -> None: if not dupes: return note_ids = set() for _, nids in dupes: note_ids.update(nids) add_tags_to_notes( parent=self, note_ids=list(note_ids), space_separated_tags=tr.browsing_duplicate(), ).run_in_background() def _on_duplicate_clicked(self, link: str) -> None: self.browser.search_for(link) self.browser.onNote()