mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12: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.table.op_executed(changes, meta, focused)
|
||||||
self.sidebar.op_executed(changes, meta, focused)
|
self.sidebar.op_executed(changes, meta, focused)
|
||||||
if changes.note or changes.notetype:
|
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
|
# fixme: this will leave the splitter shown, but with no current
|
||||||
# note being edited
|
# note being edited
|
||||||
note = self.editor.note
|
note = self.editor.note
|
||||||
|
|
|
@ -32,11 +32,7 @@ class EditCurrent(QDialog):
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def on_operation_did_execute(self, changes: OpChanges, meta: OpMeta) -> None:
|
def on_operation_did_execute(self, changes: OpChanges, meta: OpMeta) -> None:
|
||||||
if not (changes.note or changes.notetype):
|
if changes.editor and meta.handler is not self.editor:
|
||||||
return
|
|
||||||
if meta.handled_by is self.editor:
|
|
||||||
return
|
|
||||||
|
|
||||||
# reload note
|
# reload note
|
||||||
note = self.editor.note
|
note = self.editor.note
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -100,7 +100,7 @@ class Editor:
|
||||||
redrawing.
|
redrawing.
|
||||||
|
|
||||||
The editor will cause that hook to be fired when it saves changes. To avoid
|
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.
|
corresponds to this editor instance, and ignore the change if it does.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -558,7 +558,7 @@ class Editor:
|
||||||
|
|
||||||
def _save_current_note(self) -> None:
|
def _save_current_note(self) -> None:
|
||||||
"Call after note is updated with data from webview."
|
"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]]:
|
def fonts(self) -> List[Tuple[str, int, bool]]:
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -9,8 +9,8 @@ from typing import Optional
|
||||||
class OpMeta:
|
class OpMeta:
|
||||||
"""Metadata associated with an operation.
|
"""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
|
events they initiated themselves, if they have already made
|
||||||
the required changes."""
|
the required changes."""
|
||||||
|
|
||||||
handled_by: Optional[object] = None
|
handler: Optional[object] = None
|
||||||
|
|
|
@ -77,11 +77,11 @@ def set_deck_collapsed(
|
||||||
deck_id: DeckId,
|
deck_id: DeckId,
|
||||||
collapsed: bool,
|
collapsed: bool,
|
||||||
scope: DeckCollapseScope.V,
|
scope: DeckCollapseScope.V,
|
||||||
handled_by: Optional[object] = None,
|
handler: Optional[object] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
mw.perform_op(
|
mw.perform_op(
|
||||||
lambda: mw.col.decks.set_collapsed(
|
lambda: mw.col.decks.set_collapsed(
|
||||||
deck_id=deck_id, collapsed=collapsed, scope=scope
|
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)
|
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(
|
mw.perform_op(
|
||||||
lambda: mw.col.update_note(note),
|
lambda: mw.col.update_note(note),
|
||||||
meta=OpMeta(handled_by=handled_by),
|
meta=OpMeta(handler=handler),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -420,11 +420,8 @@ class SidebarTreeView(QTreeView):
|
||||||
# Refreshing
|
# Refreshing
|
||||||
###########################
|
###########################
|
||||||
|
|
||||||
def op_executed(self, op: OpChanges, meta: OpMeta, focused: bool) -> None:
|
def op_executed(self, changes: OpChanges, meta: OpMeta, focused: bool) -> None:
|
||||||
if meta.handled_by is self:
|
if changes.browser_sidebar and not meta.handler is self:
|
||||||
return
|
|
||||||
|
|
||||||
if op.tag or op.notetype or op.deck:
|
|
||||||
self._refresh_needed = True
|
self._refresh_needed = True
|
||||||
if focused:
|
if focused:
|
||||||
self.refresh_if_needed()
|
self.refresh_if_needed()
|
||||||
|
@ -984,7 +981,7 @@ class SidebarTreeView(QTreeView):
|
||||||
deck_id=DeckId(node.deck_id),
|
deck_id=DeckId(node.deck_id),
|
||||||
collapsed=not expanded,
|
collapsed=not expanded,
|
||||||
scope=DeckCollapseScope.BROWSER,
|
scope=DeckCollapseScope.BROWSER,
|
||||||
handled_by=self,
|
handler=self,
|
||||||
)
|
)
|
||||||
|
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
|
|
|
@ -180,9 +180,8 @@ class Table:
|
||||||
def redraw_cells(self) -> None:
|
def redraw_cells(self) -> None:
|
||||||
self._model.redraw_cells()
|
self._model.redraw_cells()
|
||||||
|
|
||||||
def op_executed(self, op: OpChanges, meta: OpMeta, focused: bool) -> None:
|
def op_executed(self, changes: OpChanges, meta: OpMeta, focused: bool) -> None:
|
||||||
print("op executed")
|
if changes.browser_table:
|
||||||
if op.card or op.note or op.deck or op.notetype:
|
|
||||||
self._model.empty_cache()
|
self._model.empty_cache()
|
||||||
if focused:
|
if focused:
|
||||||
self.redraw_cells()
|
self.redraw_cells()
|
||||||
|
|
|
@ -1513,6 +1513,11 @@ message OpChanges {
|
||||||
bool tag = 5;
|
bool tag = 5;
|
||||||
bool notetype = 6;
|
bool notetype = 6;
|
||||||
bool preference = 7;
|
bool preference = 7;
|
||||||
|
|
||||||
|
bool browser_table = 8;
|
||||||
|
bool browser_sidebar = 9;
|
||||||
|
bool editor = 10;
|
||||||
|
bool study_queues = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UndoStatus {
|
message UndoStatus {
|
||||||
|
|
|
@ -31,6 +31,10 @@ impl From<OpChanges> for pb::OpChanges {
|
||||||
tag: c.changes.tag,
|
tag: c.changes.tag,
|
||||||
notetype: c.changes.notetype,
|
notetype: c.changes.notetype,
|
||||||
preference: c.changes.preference,
|
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) {
|
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;
|
self.state.card_queues = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue