# 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 re
import aqt
from anki.backend_pb2 import EmptyCardsReport, NoteWithEmptyCards
from aqt import gui_hooks
from aqt.qt import QDialog, QDialogButtonBox, qconnect
from aqt.utils import TR, restoreGeom, saveGeom, tooltip, tr
def show_empty_cards(mw: aqt.main.AnkiQt) -> None:
mw.progress.start()
def on_done(fut):
mw.progress.finish()
report: EmptyCardsReport = fut.result()
if not report.notes:
tooltip(tr(TR.EMPTY_CARDS_NOT_FOUND))
return
diag = EmptyCardsDialog(mw, report)
diag.show()
mw.taskman.run_in_background(mw.col.backend.get_empty_cards, on_done)
class EmptyCardsDialog(QDialog):
silentlyClose = True
def __init__(self, mw: aqt.main.AnkiQt, report: EmptyCardsReport) -> None:
super().__init__(mw)
self.mw = mw.weakref()
self.report = report
self.form = aqt.forms.emptycards.Ui_Dialog()
self.form.setupUi(self)
restoreGeom(self, "emptycards")
self.setWindowTitle(tr(TR.EMPTY_CARDS_WINDOW_TITLE))
self.form.keep_notes.setText(tr(TR.EMPTY_CARDS_PRESERVE_NOTES_CHECKBOX))
self.form.webview.title = "empty cards"
self.form.webview.set_bridge_command(self._on_note_link_clicked, self)
gui_hooks.empty_cards_will_show(self)
# make the note ids clickable
html = re.sub(
r"\[anki:nid:(\d+)\]",
"\\1: ",
report.report,
)
style = ""
self.form.webview.stdHtml(style + html, context=self)
def on_finished(code):
saveGeom(self, "emptycards")
qconnect(self.finished, on_finished)
self._delete_button = self.form.buttonBox.addButton(
tr(TR.EMPTY_CARDS_DELETE_BUTTON), QDialogButtonBox.ActionRole
)
self._delete_button.setAutoDefault(False)
self._delete_button.clicked.connect(self._on_delete)
def _on_note_link_clicked(self, link):
browser = aqt.dialogs.open("Browser", self.mw)
browser.form.searchEdit.lineEdit().setText(link)
browser.onSearchActivated()
def _on_delete(self):
self.mw.progress.start()
def delete():
return self._delete_cards(self.form.keep_notes.isChecked())
def on_done(fut):
self.mw.progress.finish()
try:
count = fut.result()
finally:
self.close()
tooltip(tr(TR.EMPTY_CARDS_DELETED_COUNT, cards=count))
self.mw.taskman.run_in_background(delete, on_done)
def _delete_cards(self, keep_notes):
to_delete = []
for note in self.report.notes:
note: NoteWithEmptyCards = note
if keep_notes and note.will_delete_note:
# leave first card
to_delete.extend(note.card_ids[1:])
else:
to_delete.extend(note.card_ids)
self.mw.col.remove_cards_and_orphaned_notes(to_delete)
return len(to_delete)