5a094e78fa
Referencing an invalid translation should now break the build
182 lines
5.1 KiB
Python
182 lines
5.1 KiB
Python
# Copyright: Ankitects Pty Ltd and contributors
|
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import List, Optional, Sequence
|
|
|
|
import aqt
|
|
from anki.notes import NoteID
|
|
from aqt import AnkiQt, QWidget
|
|
from aqt.qt import QDialog, Qt
|
|
from aqt.utils import (
|
|
HelpPage,
|
|
disable_help_button,
|
|
openHelp,
|
|
qconnect,
|
|
restore_combo_history,
|
|
restore_combo_index_for_session,
|
|
restore_is_checked,
|
|
restoreGeom,
|
|
save_combo_history,
|
|
save_combo_index_for_session,
|
|
save_is_checked,
|
|
saveGeom,
|
|
tooltip,
|
|
tr,
|
|
)
|
|
|
|
|
|
def find_and_replace(
|
|
*,
|
|
mw: AnkiQt,
|
|
parent: QWidget,
|
|
note_ids: Sequence[NoteID],
|
|
search: str,
|
|
replacement: str,
|
|
regex: bool,
|
|
field_name: Optional[str],
|
|
match_case: bool,
|
|
) -> None:
|
|
mw.perform_op(
|
|
lambda: mw.col.find_and_replace(
|
|
note_ids=note_ids,
|
|
search=search,
|
|
replacement=replacement,
|
|
regex=regex,
|
|
field_name=field_name,
|
|
match_case=match_case,
|
|
),
|
|
success=lambda out: tooltip(
|
|
tr.findreplace_notes_updated(changed=out.count, total=len(note_ids)),
|
|
parent=parent,
|
|
),
|
|
)
|
|
|
|
|
|
def find_and_replace_tag(
|
|
*,
|
|
mw: AnkiQt,
|
|
parent: QWidget,
|
|
note_ids: Sequence[int],
|
|
search: str,
|
|
replacement: str,
|
|
regex: bool,
|
|
match_case: bool,
|
|
) -> None:
|
|
mw.perform_op(
|
|
lambda: mw.col.tags.find_and_replace(
|
|
note_ids=note_ids,
|
|
search=search,
|
|
replacement=replacement,
|
|
regex=regex,
|
|
match_case=match_case,
|
|
),
|
|
success=lambda out: tooltip(
|
|
tr.findreplace_notes_updated(changed=out.count, total=len(note_ids)),
|
|
parent=parent,
|
|
),
|
|
)
|
|
|
|
|
|
class FindAndReplaceDialog(QDialog):
|
|
COMBO_NAME = "BrowserFindAndReplace"
|
|
|
|
def __init__(
|
|
self, parent: QWidget, *, mw: AnkiQt, note_ids: Sequence[NoteID]
|
|
) -> None:
|
|
super().__init__(parent)
|
|
self.mw = mw
|
|
self.note_ids = note_ids
|
|
self.field_names: List[str] = []
|
|
|
|
# fetch field names and then show
|
|
mw.query_op(
|
|
lambda: mw.col.field_names_for_note_ids(note_ids),
|
|
success=self._show,
|
|
)
|
|
|
|
def _show(self, field_names: Sequence[str]) -> None:
|
|
# add "all fields" and "tags" to the top of the list
|
|
self.field_names = [
|
|
tr.browsing_all_fields(),
|
|
tr.editing_tags(),
|
|
] + list(field_names)
|
|
|
|
disable_help_button(self)
|
|
self.form = aqt.forms.findreplace.Ui_Dialog()
|
|
self.form.setupUi(self)
|
|
self.setWindowModality(Qt.WindowModal)
|
|
|
|
self._find_history = restore_combo_history(
|
|
self.form.find, self.COMBO_NAME + "Find"
|
|
)
|
|
self.form.find.completer().setCaseSensitivity(Qt.CaseSensitive)
|
|
self._replace_history = restore_combo_history(
|
|
self.form.replace, self.COMBO_NAME + "Replace"
|
|
)
|
|
self.form.replace.completer().setCaseSensitivity(Qt.CaseSensitive)
|
|
|
|
restore_is_checked(self.form.re, self.COMBO_NAME + "Regex")
|
|
restore_is_checked(self.form.ignoreCase, self.COMBO_NAME + "ignoreCase")
|
|
|
|
self.form.field.addItems(self.field_names)
|
|
restore_combo_index_for_session(
|
|
self.form.field, self.field_names, self.COMBO_NAME + "Field"
|
|
)
|
|
|
|
qconnect(self.form.buttonBox.helpRequested, self.show_help)
|
|
|
|
restoreGeom(self, "findreplace")
|
|
self.show()
|
|
self.form.find.setFocus()
|
|
|
|
def accept(self) -> None:
|
|
saveGeom(self, "findreplace")
|
|
save_combo_index_for_session(self.form.field, self.COMBO_NAME + "Field")
|
|
|
|
search = save_combo_history(
|
|
self.form.find, self._find_history, self.COMBO_NAME + "Find"
|
|
)
|
|
replace = save_combo_history(
|
|
self.form.replace, self._replace_history, self.COMBO_NAME + "Replace"
|
|
)
|
|
regex = self.form.re.isChecked()
|
|
match_case = not self.form.ignoreCase.isChecked()
|
|
save_is_checked(self.form.re, self.COMBO_NAME + "Regex")
|
|
save_is_checked(self.form.ignoreCase, self.COMBO_NAME + "ignoreCase")
|
|
|
|
if self.form.field.currentIndex() == 1:
|
|
# tags
|
|
find_and_replace_tag(
|
|
mw=self.mw,
|
|
parent=self.parentWidget(),
|
|
note_ids=self.note_ids,
|
|
search=search,
|
|
replacement=replace,
|
|
regex=regex,
|
|
match_case=match_case,
|
|
)
|
|
return
|
|
|
|
if self.form.field.currentIndex() == 0:
|
|
field = None
|
|
else:
|
|
field = self.field_names[self.form.field.currentIndex() - 2]
|
|
|
|
find_and_replace(
|
|
mw=self.mw,
|
|
parent=self.parentWidget(),
|
|
note_ids=self.note_ids,
|
|
search=search,
|
|
replacement=replace,
|
|
regex=regex,
|
|
field_name=field,
|
|
match_case=match_case,
|
|
)
|
|
|
|
super().accept()
|
|
|
|
def show_help(self) -> None:
|
|
openHelp(HelpPage.BROWSING_FIND_AND_REPLACE)
|