diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index c5477944e..09e409e2a 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -17,7 +17,6 @@ from anki.consts import * from anki.errors import InvalidInput, NotFoundError from anki.lang import without_unicode_isolation from anki.models import NoteType -from anki.notes import Note from anki.stats import CardStats from anki.utils import htmlToTextLine, ids2str, isMac, isWin from aqt import AnkiQt, colors, gui_hooks @@ -112,15 +111,6 @@ class DataModel(QAbstractTableModel): self.cardObjs[id] = card return self.cardObjs[id] - def refreshNote(self, note: Note) -> None: - refresh = False - for c in note.cards(): - if c.id in self.cardObjs: - del self.cardObjs[c.id] - refresh = True - if refresh: - self.layoutChanged.emit() # type: ignore - # Model interface ###################################################################### @@ -214,8 +204,9 @@ class DataModel(QAbstractTableModel): if not self.cards: return top_left = self.index(0, 0) - bottom_right = self.index(len(self.cards)-1, len(self.activeCols)-1) - self.dataChanged.emit(top_left, bottom_right) + bottom_right = self.index(len(self.cards) - 1, len(self.activeCols) - 1) + self.cardObjs = {} + self.dataChanged.emit(top_left, bottom_right) # type: ignore def reset(self) -> None: self.beginReset() @@ -513,16 +504,22 @@ class Browser(QMainWindow): self.setUpdatesEnabled(False) def on_operation_did_execute(self, changes: OpChanges) -> None: - self.setUpdatesEnabled(True) - self.model.op_executed(changes, current_top_level_widget() == self) - if (changes.note or changes.notetype) and not self.editor.is_updating_note(): - note = self.editor.note - if note: - note.load() - self.editor.set_note(note) + focused = current_top_level_widget() == self + if focused: + self.setUpdatesEnabled(True) + self.model.op_executed(changes, focused) + if changes.note or changes.notetype: + if not self.editor.is_updating_note(): + note = self.editor.note + if note: + note.load() + self.editor.set_note(note) + + self._renderPreview() def on_focus_change(self, new: Optional[QWidget], old: Optional[QWidget]) -> None: if current_top_level_widget() == self: + self.setUpdatesEnabled(True) self.model.refresh_if_needed() def setupMenus(self) -> None: @@ -860,13 +857,6 @@ QTableView {{ gridline-color: {grid} }} self._updateFlagsMenu() gui_hooks.browser_did_change_row(self) - def refreshCurrentCard(self, note: Note) -> None: - self.model.refreshNote(note) - self._renderPreview() - - def onLoadNote(self, editor: Editor) -> None: - self.refreshCurrentCard(editor.note) - def currentRow(self) -> int: idx = self.form.tableView.selectionModel().currentIndex() return idx.row() @@ -1452,9 +1442,6 @@ where id in %s""" def setupHooks(self) -> None: gui_hooks.undo_state_did_change.append(self.onUndoState) - gui_hooks.editor_did_fire_typing_timer.append(self.refreshCurrentCard) - gui_hooks.editor_did_load_note.append(self.onLoadNote) - gui_hooks.editor_did_unfocus_field.append(self.on_unfocus_field) gui_hooks.sidebar_should_refresh_decks.append(self.on_item_added) gui_hooks.sidebar_should_refresh_notetypes.append(self.on_item_added) gui_hooks.operation_will_execute.append(self.on_operation_will_execute) @@ -1463,18 +1450,12 @@ where id in %s""" def teardownHooks(self) -> None: gui_hooks.undo_state_did_change.remove(self.onUndoState) - gui_hooks.editor_did_fire_typing_timer.remove(self.refreshCurrentCard) - gui_hooks.editor_did_load_note.remove(self.onLoadNote) - gui_hooks.editor_did_unfocus_field.remove(self.on_unfocus_field) gui_hooks.sidebar_should_refresh_decks.remove(self.on_item_added) gui_hooks.sidebar_should_refresh_notetypes.remove(self.on_item_added) gui_hooks.operation_will_execute.remove(self.on_operation_will_execute) gui_hooks.operation_did_execute.remove(self.on_operation_did_execute) gui_hooks.focus_did_change.remove(self.on_focus_change) - def on_unfocus_field(self, changed: bool, note: Note, field_idx: int) -> None: - self.refreshCurrentCard(note) - # covers the tag, note and deck case def on_item_added(self, item: Any = None) -> None: self.sidebar.refresh() diff --git a/qt/aqt/editor.py b/qt/aqt/editor.py index 5a6da7b6a..4b8c0f9ca 100644 --- a/qt/aqt/editor.py +++ b/qt/aqt/editor.py @@ -90,6 +90,7 @@ _html = """ """ + class Editor: """The screen that embeds an editing widget should listen for changes via the `operation_did_execute` hook, and call set_note() when the editor needs diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index 8b5aeb0c8..f8154ab1d 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -7,6 +7,7 @@ import html import json import re import unicodedata as ucd +from enum import Enum, auto from typing import Any, Callable, List, Match, Optional, Sequence, Tuple, Union from PyQt5.QtCore import Qt @@ -41,6 +42,12 @@ from aqt.utils import ( from aqt.webview import AnkiWebView +class RefreshNeeded(Enum): + NO = auto() + NOTE_TEXT = auto() + QUEUES = auto() + + class ReviewerBottomBar: def __init__(self, reviewer: Reviewer) -> None: self.reviewer = reviewer @@ -69,7 +76,7 @@ class Reviewer: self._recordedAudio: Optional[str] = None self.typeCorrect: str = None # web init happens before this is set self.state: Optional[str] = None - self._refresh_needed = False + self._refresh_needed = RefreshNeeded.NO self.bottom = BottomBar(mw, mw.bottomWeb) hooks.card_did_leech.append(self.onLeech) @@ -78,7 +85,7 @@ class Reviewer: self.web.set_bridge_command(self._linkHandler, self) self.bottom.web.set_bridge_command(self._linkHandler, ReviewerBottomBar(self)) self._reps: int = None - self._refresh_needed = True + self._refresh_needed = RefreshNeeded.QUEUES self.refresh_if_needed() def lastCard(self) -> Optional[Card]: @@ -96,11 +103,15 @@ class Reviewer: self.card = None def refresh_if_needed(self) -> None: - if self._refresh_needed: + if self._refresh_needed is RefreshNeeded.QUEUES: self.mw.col.reset() self.nextCard() - self._refresh_needed = False self.mw.fade_in_webview() + self._refresh_needed = RefreshNeeded.NO + elif self._refresh_needed is RefreshNeeded.NOTE_TEXT: + self._redraw_current_card() + self.mw.fade_in_webview() + self._refresh_needed = RefreshNeeded.NO def op_executed(self, changes: OpChanges, focused: bool) -> bool: if changes.note and changes.kind == OpChanges.UPDATE_NOTE_TAGS: @@ -111,14 +122,21 @@ class Reviewer: self.card.load() self._update_flag_icon() elif self.mw.col.op_affects_study_queue(changes): - self._refresh_needed = True + self._refresh_needed = RefreshNeeded.QUEUES elif changes.note or changes.notetype or changes.tag: - self._refresh_needed = True + self._refresh_needed = RefreshNeeded.NOTE_TEXT - if focused and self._refresh_needed: + if focused and self._refresh_needed is not RefreshNeeded.NO: self.refresh_if_needed() - return self._refresh_needed + return self._refresh_needed is not RefreshNeeded.NO + + def _redraw_current_card(self) -> None: + self.card.load() + if self.state == "answer": + self._showAnswer() + else: + self._showQuestion() # Fetching a card ##########################################################################