mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
add booleans for various screens to OpChanges
The backend knows exactly which op has executed, and it saves us having to re-implement this logic on each client. Fixes the browser table refreshing when toggling decks.
This commit is contained in:
parent
f6ec5928ae
commit
a18bb2af12
12 changed files with 67 additions and 34 deletions
|
@ -133,7 +133,7 @@ class Browser(QMainWindow):
|
|||
self.table.op_executed(changes, meta, focused)
|
||||
self.sidebar.op_executed(changes, meta, focused)
|
||||
if changes.note or changes.notetype:
|
||||
if meta.handled_by is not self.editor:
|
||||
if meta.handler is not self.editor:
|
||||
# fixme: this will leave the splitter shown, but with no current
|
||||
# note being edited
|
||||
note = self.editor.note
|
||||
|
|
|
@ -32,21 +32,17 @@ class EditCurrent(QDialog):
|
|||
self.show()
|
||||
|
||||
def on_operation_did_execute(self, changes: OpChanges, meta: OpMeta) -> None:
|
||||
if not (changes.note or changes.notetype):
|
||||
return
|
||||
if meta.handled_by is self.editor:
|
||||
return
|
||||
if changes.editor and meta.handler is not self.editor:
|
||||
# reload note
|
||||
note = self.editor.note
|
||||
try:
|
||||
note.load()
|
||||
except NotFoundError:
|
||||
# note's been deleted
|
||||
self.cleanup_and_close()
|
||||
return
|
||||
|
||||
# reload note
|
||||
note = self.editor.note
|
||||
try:
|
||||
note.load()
|
||||
except NotFoundError:
|
||||
# note's been deleted
|
||||
self.cleanup_and_close()
|
||||
return
|
||||
|
||||
self.editor.set_note(note)
|
||||
self.editor.set_note(note)
|
||||
|
||||
def cleanup_and_close(self) -> None:
|
||||
gui_hooks.operation_did_execute.remove(self.on_operation_did_execute)
|
||||
|
|
|
@ -100,7 +100,7 @@ class Editor:
|
|||
redrawing.
|
||||
|
||||
The editor will cause that hook to be fired when it saves changes. To avoid
|
||||
an unwanted refresh, the parent widget should check if meta.handled_by
|
||||
an unwanted refresh, the parent widget should check if meta.handler
|
||||
corresponds to this editor instance, and ignore the change if it does.
|
||||
"""
|
||||
|
||||
|
@ -558,7 +558,7 @@ class Editor:
|
|||
|
||||
def _save_current_note(self) -> None:
|
||||
"Call after note is updated with data from webview."
|
||||
update_note(mw=self.mw, note=self.note, handled_by=self)
|
||||
update_note(mw=self.mw, note=self.note, handler=self)
|
||||
|
||||
def fonts(self) -> List[Tuple[str, int, bool]]:
|
||||
return [
|
||||
|
|
|
@ -9,8 +9,8 @@ from typing import Optional
|
|||
class OpMeta:
|
||||
"""Metadata associated with an operation.
|
||||
|
||||
The `handled_by` field can be used by screens to ignore change
|
||||
The `handler` field can be used by screens to ignore change
|
||||
events they initiated themselves, if they have already made
|
||||
the required changes."""
|
||||
|
||||
handled_by: Optional[object] = None
|
||||
handler: Optional[object] = None
|
||||
|
|
|
@ -77,11 +77,11 @@ def set_deck_collapsed(
|
|||
deck_id: DeckId,
|
||||
collapsed: bool,
|
||||
scope: DeckCollapseScope.V,
|
||||
handled_by: Optional[object] = None,
|
||||
handler: Optional[object] = None,
|
||||
) -> None:
|
||||
mw.perform_op(
|
||||
lambda: mw.col.decks.set_collapsed(
|
||||
deck_id=deck_id, collapsed=collapsed, scope=scope
|
||||
),
|
||||
meta=OpMeta(handled_by=handled_by),
|
||||
meta=OpMeta(handler=handler),
|
||||
)
|
||||
|
|
|
@ -22,10 +22,10 @@ def add_note(
|
|||
mw.perform_op(lambda: mw.col.add_note(note, target_deck_id), success=success)
|
||||
|
||||
|
||||
def update_note(*, mw: AnkiQt, note: Note, handled_by: Optional[object]) -> None:
|
||||
def update_note(*, mw: AnkiQt, note: Note, handler: Optional[object]) -> None:
|
||||
mw.perform_op(
|
||||
lambda: mw.col.update_note(note),
|
||||
meta=OpMeta(handled_by=handled_by),
|
||||
meta=OpMeta(handler=handler),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -420,11 +420,8 @@ class SidebarTreeView(QTreeView):
|
|||
# Refreshing
|
||||
###########################
|
||||
|
||||
def op_executed(self, op: OpChanges, meta: OpMeta, focused: bool) -> None:
|
||||
if meta.handled_by is self:
|
||||
return
|
||||
|
||||
if op.tag or op.notetype or op.deck:
|
||||
def op_executed(self, changes: OpChanges, meta: OpMeta, focused: bool) -> None:
|
||||
if changes.browser_sidebar and not meta.handler is self:
|
||||
self._refresh_needed = True
|
||||
if focused:
|
||||
self.refresh_if_needed()
|
||||
|
@ -984,7 +981,7 @@ class SidebarTreeView(QTreeView):
|
|||
deck_id=DeckId(node.deck_id),
|
||||
collapsed=not expanded,
|
||||
scope=DeckCollapseScope.BROWSER,
|
||||
handled_by=self,
|
||||
handler=self,
|
||||
)
|
||||
|
||||
for node in nodes:
|
||||
|
|
|
@ -180,9 +180,8 @@ class Table:
|
|||
def redraw_cells(self) -> None:
|
||||
self._model.redraw_cells()
|
||||
|
||||
def op_executed(self, op: OpChanges, meta: OpMeta, focused: bool) -> None:
|
||||
print("op executed")
|
||||
if op.card or op.note or op.deck or op.notetype:
|
||||
def op_executed(self, changes: OpChanges, meta: OpMeta, focused: bool) -> None:
|
||||
if changes.browser_table:
|
||||
self._model.empty_cache()
|
||||
if focused:
|
||||
self.redraw_cells()
|
||||
|
|
|
@ -1513,6 +1513,11 @@ message OpChanges {
|
|||
bool tag = 5;
|
||||
bool notetype = 6;
|
||||
bool preference = 7;
|
||||
|
||||
bool browser_table = 8;
|
||||
bool browser_sidebar = 9;
|
||||
bool editor = 10;
|
||||
bool study_queues = 11;
|
||||
}
|
||||
|
||||
message UndoStatus {
|
||||
|
|
|
@ -31,6 +31,10 @@ impl From<OpChanges> for pb::OpChanges {
|
|||
tag: c.changes.tag,
|
||||
notetype: c.changes.notetype,
|
||||
preference: c.changes.preference,
|
||||
browser_table: c.requires_browser_table_redraw(),
|
||||
browser_sidebar: c.requires_browser_sidebar_redraw(),
|
||||
editor: c.requires_editor_redraw(),
|
||||
study_queues: c.requires_study_queue_rebuild(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,3 +105,36 @@ impl<T> OpOutput<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpChanges {
|
||||
// These routines should return true even if the GUI may have
|
||||
// special handling for an action, since we need to do the right
|
||||
// thing when undoing, and if multiple windows of the same type are
|
||||
// open. For example, while toggling the expand/collapse state
|
||||
// in the sidebar will not normally trigger a full sidebar refresh,
|
||||
// requires_browser_sidebar_redraw() should still return true.
|
||||
|
||||
pub fn requires_browser_table_redraw(&self) -> bool {
|
||||
let c = &self.changes;
|
||||
c.card
|
||||
|| c.notetype
|
||||
|| (c.note && self.op != Op::AddNote)
|
||||
|| (c.deck && self.op != Op::ExpandCollapse)
|
||||
}
|
||||
|
||||
pub fn requires_browser_sidebar_redraw(&self) -> bool {
|
||||
let c = &self.changes;
|
||||
c.tag || c.deck || c.notetype
|
||||
}
|
||||
|
||||
pub fn requires_editor_redraw(&self) -> bool {
|
||||
let c = &self.changes;
|
||||
c.note || c.notetype
|
||||
}
|
||||
|
||||
pub fn requires_study_queue_rebuild(&self) -> bool {
|
||||
let c = &self.changes;
|
||||
!matches!(self.op, Op::AnswerCard | Op::ExpandCollapse)
|
||||
&& (c.card || c.deck || c.preference)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,8 +140,7 @@ impl Collection {
|
|||
}
|
||||
|
||||
pub(crate) fn maybe_clear_study_queues_after_op(&mut self, op: OpChanges) {
|
||||
if op.op != Op::AnswerCard && (op.changes.card || op.changes.deck || op.changes.preference)
|
||||
{
|
||||
if op.requires_study_queue_rebuild() {
|
||||
self.state.card_queues = None;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue