migrate more ops to CollectionOp

This commit is contained in:
Damien Elmes 2021-04-06 14:36:13 +10:00
parent 27c032a158
commit bc78b6ef17
11 changed files with 111 additions and 116 deletions

View file

@ -677,7 +677,7 @@ where id in %s"""
return
did = self.col.decks.id(ret.name)
set_card_deck(mw=self.mw, card_ids=cids, deck_id=did)
set_card_deck(parent=self, card_ids=cids, deck_id=did).run_in_background()
# legacy
@ -696,7 +696,7 @@ where id in %s"""
return
add_tags_to_notes(
parent=self, note_ids=self.selected_notes(), space_separated_tags=tags
).run(handler=self)
).run_in_background(initiator=self)
@ensure_editor_saved_on_trigger
def remove_tags_from_selected_notes(self, tags: Optional[str] = None) -> None:
@ -708,7 +708,7 @@ where id in %s"""
remove_tags_from_notes(
parent=self, note_ids=self.selected_notes(), space_separated_tags=tags
).run(handler=self)
).run_in_background(initiator=self)
def _prompt_for_tags(self, prompt: str) -> Optional[str]:
(tags, ok) = getTag(self, self.col, prompt)
@ -719,7 +719,7 @@ where id in %s"""
@ensure_editor_saved_on_trigger
def clear_unused_tags(self) -> None:
clear_unused_tags(parent=self).run()
clear_unused_tags(parent=self).run_in_background()
addTags = add_tags_to_selected_notes
deleteTags = remove_tags_from_selected_notes
@ -760,7 +760,9 @@ where id in %s"""
if flag == self.card.user_flag():
flag = 0
set_card_flag(mw=self.mw, card_ids=self.selected_cards(), flag=flag)
set_card_flag(
parent=self, card_ids=self.selected_cards(), flag=flag
).run_in_background()
def _update_flags_menu(self) -> None:
flag = self.card and self.card.user_flag()
@ -859,7 +861,7 @@ where id in %s"""
######################################################################
def undo(self) -> None:
undo(mw=self.mw, parent=self)
undo(parent=self)
def onUndoState(self, on: bool) -> None:
self.form.actionUndo.setEnabled(on)

View file

@ -278,7 +278,9 @@ class DeckBrowser:
if not new_name or new_name == deck.name:
return
else:
rename_deck(mw=self.mw, deck_id=did, new_name=new_name)
rename_deck(
parent=self.mw, deck_id=did, new_name=new_name
).run_in_background()
self.mw.query_op(lambda: self.mw.col.get_deck(did), success=prompt)
@ -293,18 +295,20 @@ class DeckBrowser:
if node:
node.collapsed = not node.collapsed
set_deck_collapsed(
mw=self.mw,
parent=self.mw,
deck_id=did,
collapsed=node.collapsed,
scope=DeckCollapseScope.REVIEWER,
)
).run_in_background()
self._renderPage(reuse=True)
def _handle_drag_and_drop(self, source: DeckId, target: DeckId) -> None:
reparent_decks(mw=self.mw, parent=self.mw, deck_ids=[source], new_parent=target)
reparent_decks(
parent=self.mw, deck_ids=[source], new_parent=target
).run_in_background()
def _delete(self, did: DeckId) -> None:
remove_decks(mw=self.mw, parent=self.mw, deck_ids=[did])
remove_decks(parent=self.mw, deck_ids=[did]).run_in_background()
# Top buttons
######################################################################
@ -335,7 +339,8 @@ class DeckBrowser:
openLink(f"{aqt.appShared}decks/")
def _on_create(self) -> None:
add_deck_dialog(mw=self.mw, parent=self.mw)
if op := add_deck_dialog(parent=self.mw):
op.run_in_background()
######################################################################

View file

@ -21,7 +21,6 @@ from typing import (
List,
Literal,
Optional,
Protocol,
Sequence,
TextIO,
Tuple,
@ -40,15 +39,7 @@ import aqt.toolbar
import aqt.webview
from anki import hooks
from anki._backend import RustBackend as _RustBackend
from anki.collection import (
Collection,
Config,
OpChanges,
OpChangesAfterUndo,
OpChangesWithCount,
OpChangesWithId,
UndoStatus,
)
from anki.collection import Collection, Config, OpChanges, UndoStatus
from anki.decks import DeckDict, DeckId
from anki.hooks import runHook
from anki.notes import NoteId
@ -1198,7 +1189,7 @@ title="%s" %s>%s</button>""" % (
def undo(self) -> None:
"Call collection_ops.py:undo() directly instead."
undo(mw=self, parent=self)
undo(parent=self)
def update_undo_actions(self, status: Optional[UndoStatus] = None) -> None:
"""Update menu text and enable/disable menu item as appropriate.

View file

@ -77,11 +77,13 @@ class CollectionOp(Generic[ResultWithChanges]):
self._success = success
return self
def failure(self, failure: Optional[CollectionOpFailureCallback]) -> CollectionOp[ResultWithChanges]:
def failure(
self, failure: Optional[CollectionOpFailureCallback]
) -> CollectionOp[ResultWithChanges]:
self._failure = failure
return self
def run(self, *, handler: Optional[object] = None) -> None:
def run_in_background(self, *, initiator: Optional[object] = None) -> None:
aqt.mw._increase_background_ops()
def wrapped_op() -> ResultWithChanges:
@ -110,7 +112,7 @@ class CollectionOp(Generic[ResultWithChanges]):
status = aqt.mw.col.undo_status()
aqt.mw._update_undo_actions_for_status_and_save(status)
# fire change hooks
self._fire_change_hooks_after_op_performed(result, handler)
self._fire_change_hooks_after_op_performed(result, initiator)
aqt.mw.taskman.with_progress(wrapped_op, wrapped_done)

View file

@ -3,28 +3,25 @@
from __future__ import annotations
from typing import Optional, Sequence
from typing import Sequence
from anki.cards import CardId
from anki.collection import OpChanges
from anki.decks import DeckId
from aqt import AnkiQt
from aqt.main import PerformOpOptionalSuccessCallback
from aqt.operations import CollectionOp
from aqt.qt import QWidget
def set_card_deck(*, mw: AnkiQt, card_ids: Sequence[CardId], deck_id: DeckId) -> None:
mw.perform_op(lambda: mw.col.set_deck(card_ids, deck_id))
def set_card_deck(
*, parent: QWidget, card_ids: Sequence[CardId], deck_id: DeckId
) -> CollectionOp[OpChanges]:
return CollectionOp(parent, lambda col: col.set_deck(card_ids, deck_id))
def set_card_flag(
*,
mw: AnkiQt,
parent: QWidget,
card_ids: Sequence[CardId],
flag: int,
handler: Optional[object] = None,
success: PerformOpOptionalSuccessCallback = None,
) -> None:
mw.perform_op(
lambda: mw.col.set_user_flag_for_cards(flag, card_ids),
handler=handler,
success=success,
)
) -> CollectionOp[OpChanges]:
return CollectionOp(parent, lambda col: col.set_user_flag_for_cards(flag, card_ids))

View file

@ -3,34 +3,34 @@
from __future__ import annotations
import aqt
from anki.collection import LegacyCheckpoint, LegacyReviewUndo, OpChangesAfterUndo
from anki.collection import LegacyCheckpoint, LegacyReviewUndo
from anki.errors import UndoEmpty
from anki.types import assert_exhaustive
from aqt import gui_hooks
from aqt.operations import CollectionOp
from aqt.qt import QWidget
from aqt.utils import showInfo, showWarning, tooltip, tr
def undo(*, mw: aqt.AnkiQt, parent: QWidget) -> None:
def undo(*, parent: QWidget) -> None:
"Undo the last operation, and refresh the UI."
def on_success(out: OpChangesAfterUndo) -> None:
mw.update_undo_actions(out.new_status)
tooltip(tr.undo_action_undone(action=out.operation), parent=parent)
def on_failure(exc: Exception) -> None:
if isinstance(exc, UndoEmpty):
# backend has no undo, but there may be a checkpoint
# or v1/v2 review waiting
_legacy_undo(mw=mw, parent=parent)
_legacy_undo(parent=parent)
else:
showWarning(str(exc), parent=parent)
mw.perform_op(mw.col.undo, success=on_success, failure=on_failure)
CollectionOp(parent, lambda col: col.undo()).success(
lambda out: tooltip(tr.undo_action_undone(action=out.operation), parent=parent)
).failure(on_failure).run_in_background()
def _legacy_undo(*, mw: aqt.AnkiQt, parent: QWidget) -> None:
def _legacy_undo(*, parent: QWidget) -> None:
from aqt import mw
reviewing = mw.state == "review"
just_refresh_reviewer = False

View file

@ -5,81 +5,74 @@ from __future__ import annotations
from typing import Optional, Sequence
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithId
from anki.decks import DeckCollapseScope, DeckId
from aqt import AnkiQt, QWidget
from aqt.main import PerformOpOptionalSuccessCallback
from aqt import QWidget
from aqt.operations import CollectionOp
from aqt.utils import getOnlyText, tooltip, tr
def remove_decks(
*,
mw: AnkiQt,
parent: QWidget,
deck_ids: Sequence[DeckId],
) -> None:
mw.perform_op(
lambda: mw.col.decks.remove(deck_ids),
success=lambda out: tooltip(
tr.browsing_cards_deleted(count=out.count), parent=parent
),
) -> CollectionOp[OpChangesWithCount]:
return CollectionOp(parent, lambda col: col.decks.remove(deck_ids)).success(
lambda out: tooltip(tr.browsing_cards_deleted(count=out.count), parent=parent)
)
def reparent_decks(
*, mw: AnkiQt, parent: QWidget, deck_ids: Sequence[DeckId], new_parent: DeckId
) -> None:
mw.perform_op(
lambda: mw.col.decks.reparent(deck_ids=deck_ids, new_parent=new_parent),
success=lambda out: tooltip(
*, parent: QWidget, deck_ids: Sequence[DeckId], new_parent: DeckId
) -> CollectionOp[OpChangesWithCount]:
return CollectionOp(
parent, lambda col: col.decks.reparent(deck_ids=deck_ids, new_parent=new_parent)
).success(
lambda out: tooltip(
tr.browsing_reparented_decks(count=out.count), parent=parent
),
)
)
def rename_deck(
*,
mw: AnkiQt,
parent: QWidget,
deck_id: DeckId,
new_name: str,
) -> None:
mw.perform_op(
lambda: mw.col.decks.rename(deck_id, new_name),
) -> CollectionOp[OpChanges]:
return CollectionOp(
parent,
lambda col: col.decks.rename(deck_id, new_name),
)
def add_deck_dialog(
*,
mw: AnkiQt,
parent: QWidget,
default_text: str = "",
success: PerformOpOptionalSuccessCallback = None,
) -> None:
) -> Optional[CollectionOp[OpChangesWithId]]:
if name := getOnlyText(
tr.decks_new_deck_name(), default=default_text, parent=parent
).strip():
add_deck(mw=mw, name=name, success=success)
return add_deck(parent=parent, name=name)
else:
return None
def add_deck(
*, mw: AnkiQt, name: str, success: PerformOpOptionalSuccessCallback = None
) -> None:
mw.perform_op(
lambda: mw.col.decks.add_normal_deck_with_name(name),
success=success,
)
def add_deck(*, parent: QWidget, name: str) -> CollectionOp[OpChangesWithId]:
return CollectionOp(parent, lambda col: col.decks.add_normal_deck_with_name(name))
def set_deck_collapsed(
*,
mw: AnkiQt,
parent: QWidget,
deck_id: DeckId,
collapsed: bool,
scope: DeckCollapseScope.V,
handler: Optional[object] = None,
) -> None:
mw.perform_op(
lambda: mw.col.decks.set_collapsed(
) -> CollectionOp[OpChanges]:
return CollectionOp(
parent,
lambda col: col.decks.set_collapsed(
deck_id=deck_id, collapsed=collapsed, scope=scope
),
handler=handler,
)

View file

@ -5,9 +5,9 @@ from __future__ import annotations
from typing import Sequence
from anki.collection import OpChangesWithCount
from anki.collection import OpChanges, OpChangesWithCount
from anki.notes import NoteId
from aqt import AnkiQt, QWidget
from aqt import QWidget
from aqt.operations import CollectionOp
from aqt.utils import showInfo, tooltip, tr
@ -17,7 +17,7 @@ def add_tags_to_notes(
parent: QWidget,
note_ids: Sequence[NoteId],
space_separated_tags: str,
) -> CollectionOp:
) -> CollectionOp[OpChangesWithCount]:
return CollectionOp(
parent, lambda col: col.tags.bulk_add(note_ids, space_separated_tags)
).success(
@ -30,7 +30,7 @@ def remove_tags_from_notes(
parent: QWidget,
note_ids: Sequence[NoteId],
space_separated_tags: str,
) -> CollectionOp:
) -> CollectionOp[OpChangesWithCount]:
return CollectionOp(
parent, lambda col: col.tags.bulk_remove(note_ids, space_separated_tags)
).success(
@ -38,7 +38,7 @@ def remove_tags_from_notes(
)
def clear_unused_tags(*, parent: QWidget) -> CollectionOp:
def clear_unused_tags(*, parent: QWidget) -> CollectionOp[OpChangesWithCount]:
return CollectionOp(parent, lambda col: col.tags.clear_unused_tags()).success(
lambda out: tooltip(
tr.browsing_removed_unused_tags_count(count=out.count), parent=parent
@ -51,7 +51,7 @@ def rename_tag(
parent: QWidget,
current_name: str,
new_name: str,
) -> CollectionOp:
) -> CollectionOp[OpChangesWithCount]:
def success(out: OpChangesWithCount) -> None:
if out.count:
tooltip(tr.browsing_notes_updated(count=out.count), parent=parent)
@ -66,7 +66,7 @@ def rename_tag(
def remove_tags_from_all_notes(
*, parent: QWidget, space_separated_tags: str
) -> CollectionOp:
) -> CollectionOp[OpChangesWithCount]:
return CollectionOp(
parent, lambda col: col.tags.remove(space_separated_tags=space_separated_tags)
).success(
@ -76,7 +76,7 @@ def remove_tags_from_all_notes(
def reparent_tags(
*, parent: QWidget, tags: Sequence[str], new_parent: str
) -> CollectionOp:
) -> CollectionOp[OpChangesWithCount]:
return CollectionOp(
parent, lambda col: col.tags.reparent(tags=tags, new_parent=new_parent)
).success(
@ -84,7 +84,9 @@ def reparent_tags(
)
def set_tag_collapsed(*, parent: QWidget, tag: str, collapsed: bool) -> CollectionOp:
def set_tag_collapsed(
*, parent: QWidget, tag: str, collapsed: bool
) -> CollectionOp[OpChanges]:
return CollectionOp(
parent, lambda col: col.tags.set_collapsed(tag=tag, collapsed=collapsed)
)

View file

@ -835,13 +835,9 @@ time = %(time)d;
else:
flag = desired_flag
set_card_flag(
mw=self.mw,
card_ids=[self.card.id],
flag=flag,
handler=self,
success=redraw_flag,
)
set_card_flag(parent=self.mw, card_ids=[self.card.id], flag=flag).success(
redraw_flag
).run_in_background(initiator=self)
def toggle_mark_on_current_note(self) -> None:
def redraw_mark(out: OpChangesWithCount) -> None:
@ -852,13 +848,13 @@ time = %(time)d;
if note.has_tag(MARKED_TAG):
remove_tags_from_notes(
parent=self.mw, note_ids=[note.id], space_separated_tags=MARKED_TAG
).success(redraw_mark).run(handler=self)
).success(redraw_mark).run_in_background(initiator=self)
else:
add_tags_to_notes(
parent=self.mw,
note_ids=[note.id],
space_separated_tags=MARKED_TAG,
).success(redraw_mark).run(handler=self)
).success(redraw_mark).run_in_background(initiator=self)
def on_set_due(self) -> None:
if self.mw.state != "review" or not self.card:

View file

@ -631,8 +631,8 @@ class SidebarTreeView(QTreeView):
new_parent = DeckId(target.id)
reparent_decks(
mw=self.mw, parent=self.browser, deck_ids=deck_ids, new_parent=new_parent
)
parent=self.browser, deck_ids=deck_ids, new_parent=new_parent
).run_in_background()
return True
@ -652,7 +652,9 @@ class SidebarTreeView(QTreeView):
else:
new_parent = target.full_name
reparent_tags(parent=self.browser, tags=tags, new_parent=new_parent).run()
reparent_tags(
parent=self.browser, tags=tags, new_parent=new_parent
).run_in_background()
return True
@ -948,7 +950,7 @@ class SidebarTreeView(QTreeView):
full_name = head + node.name
return lambda expanded: set_tag_collapsed(
parent=self, tag=full_name, collapsed=not expanded
).run()
).run_in_background()
for node in nodes:
item = SidebarItem(
@ -993,11 +995,12 @@ class SidebarTreeView(QTreeView):
) -> None:
def toggle_expand(node: DeckTreeNode) -> Callable[[bool], None]:
return lambda expanded: set_deck_collapsed(
mw=self.mw,
parent=self,
deck_id=DeckId(node.deck_id),
collapsed=not expanded,
scope=DeckCollapseScope.BROWSER,
handler=self,
).run_in_background(
initiator=self,
)
for node in nodes:
@ -1192,15 +1195,15 @@ class SidebarTreeView(QTreeView):
return
rename_deck(
mw=self.mw,
parent=self,
deck_id=deck_id,
new_name=full_name,
)
).run_in_background()
self.mw.query_op(lambda: self.mw.col.get_deck(deck_id), success=after_fetch)
def delete_decks(self, _item: SidebarItem) -> None:
remove_decks(mw=self.mw, parent=self.browser, deck_ids=self._selected_decks())
remove_decks(parent=self, deck_ids=self._selected_decks()).run_in_background()
# Tags
###########################
@ -1209,7 +1212,9 @@ class SidebarTreeView(QTreeView):
tags = self.mw.col.tags.join(self._selected_tags())
item.name = "..."
remove_tags_from_all_notes(parent=self.browser, space_separated_tags=tags).run()
remove_tags_from_all_notes(
parent=self.browser, space_separated_tags=tags
).run_in_background()
def rename_tag(self, item: SidebarItem, new_name: str) -> None:
if not new_name or new_name == item.name:
@ -1227,7 +1232,7 @@ class SidebarTreeView(QTreeView):
parent=self.browser,
current_name=old_name,
new_name=new_name,
).run()
).run_in_background()
# Saved searches
####################################

View file

@ -175,4 +175,6 @@ class StudyDeck(QDialog):
QDialog.accept(self)
add_deck_dialog(mw=self.mw, parent=self, default_text=default, success=success)
add_deck_dialog(parent=self, default_text=default).success(
success
).run_in_background()