From b887032244c901222ac29cf6cf320af64634fe70 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sat, 8 May 2021 15:08:45 +1000 Subject: [PATCH] split browser dialogs into separate files --- qt/aqt/browser/__init__.py | 6 +- qt/aqt/browser/browser.py | 44 ++---- qt/aqt/browser/card_info.py | 39 ++++++ .../{dialogs.py => change_notetype.py} | 123 +---------------- qt/aqt/browser/find_and_replace.py | 128 ++++++++++++++++++ 5 files changed, 180 insertions(+), 160 deletions(-) create mode 100644 qt/aqt/browser/card_info.py rename qt/aqt/browser/{dialogs.py => change_notetype.py} (63%) create mode 100644 qt/aqt/browser/find_and_replace.py diff --git a/qt/aqt/browser/__init__.py b/qt/aqt/browser/__init__.py index 9fd777224..d8f3f82a1 100644 --- a/qt/aqt/browser/__init__.py +++ b/qt/aqt/browser/__init__.py @@ -7,8 +7,9 @@ import sys import aqt from .browser import Browser -from .dialogs import CardInfoDialog, ChangeModel, FindAndReplaceDialog -from .previewer import BrowserPreviewer, MultiCardPreviewer, Previewer + +# aliases for legacy pathnames +from .change_notetype import ChangeModel from .sidebar import ( SidebarItem, SidebarItemType, @@ -35,7 +36,6 @@ from .table import ( Table, ) -# aliases for legacy pathnames sys.modules["aqt.sidebar"] = sys.modules["aqt.browser.sidebar"] aqt.sidebar = sys.modules["aqt.browser.sidebar"] # type: ignore sys.modules["aqt.previewer"] = sys.modules["aqt.browser.previewer"] diff --git a/qt/aqt/browser/browser.py b/qt/aqt/browser/browser.py index d4910231c..c2b581137 100644 --- a/qt/aqt/browser/browser.py +++ b/qt/aqt/browser/browser.py @@ -13,15 +13,9 @@ from anki.consts import * from anki.errors import NotFoundError from anki.lang import without_unicode_isolation from anki.notes import NoteId -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 -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.operations.card import set_card_deck, set_card_flag @@ -61,7 +55,14 @@ from aqt.utils import ( skip_if_selection_is_empty, tr, ) -from aqt.webview import AnkiWebView + +from .card_info import CardInfoDialog +from .change_notetype import ChangeModel +from .find_and_replace import FindAndReplaceDialog +from .previewer import BrowserPreviewer as PreviewDialog +from .previewer import Previewer +from .sidebar import SidebarTreeView +from .table import Table class Browser(QMainWindow): @@ -478,34 +479,7 @@ class Browser(QMainWindow): if not self.card: return - info, cs = self._cardInfoData() - reps = self._revlogData(cs) - - card_info_dialog = CardInfoDialog(self) - l = QVBoxLayout() - l.setContentsMargins(0, 0, 0, 0) - w = AnkiWebView(title="browser card info") - l.addWidget(w) - w.stdHtml(info + "

" + reps, context=card_info_dialog) - bb = QDialogButtonBox(QDialogButtonBox.Close) - l.addWidget(bb) - qconnect(bb.rejected, card_info_dialog.reject) - card_info_dialog.setLayout(l) - card_info_dialog.setWindowModality(Qt.WindowModal) - card_info_dialog.resize(500, 400) - restoreGeom(card_info_dialog, "revlog") - card_info_dialog.show() - - def _cardInfoData(self) -> Tuple[str, CardStats]: - cs = CardStats(self.col, self.card) - rep = cs.report(include_revlog=True) - return rep, cs - - # legacy - revlog used to be generated here, and some add-ons - # wrapped this function - - def _revlogData(self, cs: CardStats) -> str: - return "" + CardInfoDialog(parent=self, mw=self.mw, card=self.card) # Menu helpers ###################################################################### diff --git a/qt/aqt/browser/card_info.py b/qt/aqt/browser/card_info.py new file mode 100644 index 000000000..dc9e19372 --- /dev/null +++ b/qt/aqt/browser/card_info.py @@ -0,0 +1,39 @@ +# 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 aqt +from anki.cards import Card +from anki.stats import CardStats +from aqt.qt import * +from aqt.utils import disable_help_button, qconnect, restoreGeom, saveGeom +from aqt.webview import AnkiWebView + + +class CardInfoDialog(QDialog): + silentlyClose = True + + def __init__(self, parent: QWidget, mw: aqt.AnkiQt, card: Card) -> None: + super().__init__(parent) + disable_help_button(self) + cs = CardStats(mw.col, card) + info = cs.report(include_revlog=True) + + l = QVBoxLayout() + l.setContentsMargins(0, 0, 0, 0) + w = AnkiWebView(title="browser card info") + l.addWidget(w) + w.stdHtml(info + "

", context=self) + bb = QDialogButtonBox(QDialogButtonBox.Close) + l.addWidget(bb) + qconnect(bb.rejected, self.reject) + self.setLayout(l) + self.setWindowModality(Qt.WindowModal) + self.resize(500, 400) + restoreGeom(self, "revlog") + self.show() + + def reject(self) -> None: + saveGeom(self, "revlog") + return QDialog.reject(self) diff --git a/qt/aqt/browser/dialogs.py b/qt/aqt/browser/change_notetype.py similarity index 63% rename from qt/aqt/browser/dialogs.py rename to qt/aqt/browser/change_notetype.py index eff6675ee..13fad6369 100644 --- a/qt/aqt/browser/dialogs.py +++ b/qt/aqt/browser/change_notetype.py @@ -9,9 +9,7 @@ import aqt from anki.consts import * from anki.models import NotetypeDict from anki.notes import NoteId -from aqt import AnkiQt, QWidget, gui_hooks -from aqt.operations.note import find_and_replace -from aqt.operations.tag import find_and_replace_tag +from aqt import QWidget, gui_hooks from aqt.qt import * from aqt.utils import ( HelpPage, @@ -19,13 +17,7 @@ from aqt.utils import ( 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, tr, ) @@ -213,116 +205,3 @@ class ChangeModel(QDialog): def onHelp(self) -> None: openHelp(HelpPage.BROWSING_OTHER_MENU_ITEMS) - - -class CardInfoDialog(QDialog): - silentlyClose = True - - def __init__(self, browser: aqt.browser.Browser) -> None: - super().__init__(browser) - self.browser = browser - disable_help_button(self) - - def reject(self) -> None: - saveGeom(self, "revlog") - return QDialog.reject(self) - - -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") - - # tags? - if self.form.field.currentIndex() == 1: - find_and_replace_tag( - parent=self.parentWidget(), - note_ids=self.note_ids, - search=search, - replacement=replace, - regex=regex, - match_case=match_case, - ).run_in_background() - else: - # fields - if self.form.field.currentIndex() == 0: - field = None - else: - field = self.field_names[self.form.field.currentIndex() - 2] - - find_and_replace( - parent=self.parentWidget(), - note_ids=self.note_ids, - search=search, - replacement=replace, - regex=regex, - field_name=field, - match_case=match_case, - ).run_in_background() - - super().accept() - - def show_help(self) -> None: - openHelp(HelpPage.BROWSING_FIND_AND_REPLACE) diff --git a/qt/aqt/browser/find_and_replace.py b/qt/aqt/browser/find_and_replace.py new file mode 100644 index 000000000..c82db8aa6 --- /dev/null +++ b/qt/aqt/browser/find_and_replace.py @@ -0,0 +1,128 @@ +# 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, Sequence + +import aqt +from anki.notes import NoteId +from aqt import AnkiQt +from aqt.operations.note import find_and_replace +from aqt.operations.tag import find_and_replace_tag +from aqt.qt import * +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, + tr, +) + + +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") + + # tags? + if self.form.field.currentIndex() == 1: + find_and_replace_tag( + parent=self.parentWidget(), + note_ids=self.note_ids, + search=search, + replacement=replace, + regex=regex, + match_case=match_case, + ).run_in_background() + else: + # fields + if self.form.field.currentIndex() == 0: + field = None + else: + field = self.field_names[self.form.field.currentIndex() - 2] + + find_and_replace( + parent=self.parentWidget(), + note_ids=self.note_ids, + search=search, + replacement=replace, + regex=regex, + field_name=field, + match_case=match_case, + ).run_in_background() + + super().accept() + + def show_help(self) -> None: + openHelp(HelpPage.BROWSING_FIND_AND_REPLACE)