NF: CardID type
This commit is contained in:
parent
6ac540927a
commit
986efeed19
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import pprint
|
import pprint
|
||||||
import time
|
import time
|
||||||
from typing import List, Optional
|
from typing import List, NewType, Optional
|
||||||
|
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
import anki._backend.backend_pb2 as _pb
|
import anki._backend.backend_pb2 as _pb
|
||||||
@ -26,6 +26,9 @@ from anki.sound import AVTag
|
|||||||
# - rev queue: integer day
|
# - rev queue: integer day
|
||||||
# - lrn queue: integer timestamp
|
# - lrn queue: integer timestamp
|
||||||
|
|
||||||
|
# types
|
||||||
|
CardID = NewType("CardID", int)
|
||||||
|
|
||||||
|
|
||||||
class Card:
|
class Card:
|
||||||
_note: Optional[Note]
|
_note: Optional[Note]
|
||||||
@ -33,9 +36,10 @@ class Card:
|
|||||||
lastIvl: int
|
lastIvl: int
|
||||||
ord: int
|
ord: int
|
||||||
nid: anki.notes.NoteID
|
nid: anki.notes.NoteID
|
||||||
|
id: CardID
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, col: anki.collection.Collection, id: Optional[int] = None
|
self, col: anki.collection.Collection, id: Optional[CardID] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
self.timerStarted = None
|
self.timerStarted = None
|
||||||
@ -56,7 +60,7 @@ class Card:
|
|||||||
def _load_from_backend_card(self, c: _pb.Card) -> None:
|
def _load_from_backend_card(self, c: _pb.Card) -> None:
|
||||||
self._render_output = None
|
self._render_output = None
|
||||||
self._note = None
|
self._note = None
|
||||||
self.id = c.id
|
self.id = CardID(c.id)
|
||||||
self.nid = anki.notes.NoteID(c.note_id)
|
self.nid = anki.notes.NoteID(c.note_id)
|
||||||
self.did = c.deck_id
|
self.did = c.deck_id
|
||||||
self.ord = c.template_idx
|
self.ord = c.template_idx
|
||||||
|
@ -34,7 +34,7 @@ from dataclasses import dataclass, field
|
|||||||
import anki.latex
|
import anki.latex
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
from anki._backend import RustBackend
|
from anki._backend import RustBackend
|
||||||
from anki.cards import Card
|
from anki.cards import Card, CardID
|
||||||
from anki.config import Config, ConfigManager
|
from anki.config import Config, ConfigManager
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.dbproxy import DBProxy
|
from anki.dbproxy import DBProxy
|
||||||
@ -319,7 +319,7 @@ class Collection:
|
|||||||
# Object creation helpers
|
# Object creation helpers
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def get_card(self, id: int) -> Card:
|
def get_card(self, id: CardID) -> Card:
|
||||||
return Card(self, id)
|
return Card(self, id)
|
||||||
|
|
||||||
def update_card(self, card: Card) -> None:
|
def update_card(self, card: Card) -> None:
|
||||||
@ -379,7 +379,7 @@ class Collection:
|
|||||||
hooks.notes_will_be_deleted(self, note_ids)
|
hooks.notes_will_be_deleted(self, note_ids)
|
||||||
return self._backend.remove_notes(note_ids=note_ids, card_ids=[])
|
return self._backend.remove_notes(note_ids=note_ids, card_ids=[])
|
||||||
|
|
||||||
def remove_notes_by_card(self, card_ids: List[int]) -> None:
|
def remove_notes_by_card(self, card_ids: List[CardID]) -> None:
|
||||||
if hooks.notes_will_be_deleted.count():
|
if hooks.notes_will_be_deleted.count():
|
||||||
nids = self.db.list(
|
nids = self.db.list(
|
||||||
f"select nid from cards where id in {ids2str(card_ids)}"
|
f"select nid from cards where id in {ids2str(card_ids)}"
|
||||||
@ -387,8 +387,8 @@ class Collection:
|
|||||||
hooks.notes_will_be_deleted(self, nids)
|
hooks.notes_will_be_deleted(self, nids)
|
||||||
self._backend.remove_notes(note_ids=[], card_ids=card_ids)
|
self._backend.remove_notes(note_ids=[], card_ids=card_ids)
|
||||||
|
|
||||||
def card_ids_of_note(self, note_id: NoteID) -> Sequence[int]:
|
def card_ids_of_note(self, note_id: NoteID) -> Sequence[CardID]:
|
||||||
return self._backend.cards_of_note(note_id)
|
return [CardID(id) for id in self._backend.cards_of_note(note_id)]
|
||||||
|
|
||||||
def defaults_for_adding(
|
def defaults_for_adding(
|
||||||
self, *, current_review_card: Optional[Card]
|
self, *, current_review_card: Optional[Card]
|
||||||
@ -447,11 +447,11 @@ class Collection:
|
|||||||
def cardCount(self) -> Any:
|
def cardCount(self) -> Any:
|
||||||
return self.db.scalar("select count() from cards")
|
return self.db.scalar("select count() from cards")
|
||||||
|
|
||||||
def remove_cards_and_orphaned_notes(self, card_ids: Sequence[int]) -> None:
|
def remove_cards_and_orphaned_notes(self, card_ids: Sequence[CardID]) -> None:
|
||||||
"You probably want .remove_notes_by_card() instead."
|
"You probably want .remove_notes_by_card() instead."
|
||||||
self._backend.remove_cards(card_ids=card_ids)
|
self._backend.remove_cards(card_ids=card_ids)
|
||||||
|
|
||||||
def set_deck(self, card_ids: Sequence[int], deck_id: int) -> OpChanges:
|
def set_deck(self, card_ids: Sequence[CardID], deck_id: int) -> OpChanges:
|
||||||
return self._backend.set_deck(card_ids=card_ids, deck_id=deck_id)
|
return self._backend.set_deck(card_ids=card_ids, deck_id=deck_id)
|
||||||
|
|
||||||
def get_empty_cards(self) -> EmptyCardsReport:
|
def get_empty_cards(self) -> EmptyCardsReport:
|
||||||
@ -459,10 +459,10 @@ class Collection:
|
|||||||
|
|
||||||
# legacy
|
# legacy
|
||||||
|
|
||||||
def remCards(self, ids: List[int], notes: bool = True) -> None:
|
def remCards(self, ids: List[CardID], notes: bool = True) -> None:
|
||||||
self.remove_cards_and_orphaned_notes(ids)
|
self.remove_cards_and_orphaned_notes(ids)
|
||||||
|
|
||||||
def emptyCids(self) -> List[int]:
|
def emptyCids(self) -> List[CardID]:
|
||||||
print("emptyCids() will go away")
|
print("emptyCids() will go away")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@ -495,7 +495,7 @@ class Collection:
|
|||||||
query: str,
|
query: str,
|
||||||
order: Union[bool, str, BuiltinSort.Kind.V] = False,
|
order: Union[bool, str, BuiltinSort.Kind.V] = False,
|
||||||
reverse: bool = False,
|
reverse: bool = False,
|
||||||
) -> Sequence[int]:
|
) -> Sequence[CardID]:
|
||||||
"""Return card ids matching the provided search.
|
"""Return card ids matching the provided search.
|
||||||
|
|
||||||
To programmatically construct a search string, see .build_search_string().
|
To programmatically construct a search string, see .build_search_string().
|
||||||
@ -525,7 +525,9 @@ class Collection:
|
|||||||
mode = _pb.SortOrder(
|
mode = _pb.SortOrder(
|
||||||
builtin=_pb.SortOrder.Builtin(kind=order, reverse=reverse)
|
builtin=_pb.SortOrder.Builtin(kind=order, reverse=reverse)
|
||||||
)
|
)
|
||||||
return self._backend.search_cards(search=query, order=mode)
|
return [
|
||||||
|
CardID(id) for id in self._backend.search_cards(search=query, order=mode)
|
||||||
|
]
|
||||||
|
|
||||||
def find_notes(self, *terms: Union[str, SearchNode]) -> Sequence[NoteID]:
|
def find_notes(self, *terms: Union[str, SearchNode]) -> Sequence[NoteID]:
|
||||||
"""Return note ids matching the provided search or searches.
|
"""Return note ids matching the provided search or searches.
|
||||||
@ -740,7 +742,7 @@ class Collection:
|
|||||||
|
|
||||||
return CollectionStats(self)
|
return CollectionStats(self)
|
||||||
|
|
||||||
def card_stats(self, card_id: int, include_revlog: bool) -> str:
|
def card_stats(self, card_id: CardID, include_revlog: bool) -> str:
|
||||||
import anki.stats as st
|
import anki.stats as st
|
||||||
|
|
||||||
if include_revlog:
|
if include_revlog:
|
||||||
@ -1033,7 +1035,7 @@ table.review-log {{ {revlog_style} }}
|
|||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def set_user_flag_for_cards(self, flag: int, cids: Sequence[int]) -> OpChanges:
|
def set_user_flag_for_cards(self, flag: int, cids: Sequence[CardID]) -> OpChanges:
|
||||||
return self._backend.set_flag(card_ids=cids, flag=flag)
|
return self._backend.set_flag(card_ids=cids, flag=flag)
|
||||||
|
|
||||||
def set_wants_abort(self) -> None:
|
def set_wants_abort(self) -> None:
|
||||||
|
@ -11,6 +11,7 @@ from typing import Any, Dict, Iterable, List, NewType, Optional, Sequence, Tuple
|
|||||||
|
|
||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
import anki._backend.backend_pb2 as _pb
|
import anki._backend.backend_pb2 as _pb
|
||||||
|
from anki.cards import CardID
|
||||||
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithID
|
from anki.collection import OpChanges, OpChangesWithCount, OpChangesWithID
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.errors import NotFoundError
|
from anki.errors import NotFoundError
|
||||||
@ -406,7 +407,7 @@ class DeckManager:
|
|||||||
return deck["name"]
|
return deck["name"]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def setDeck(self, cids: List[int], did: int) -> None:
|
def setDeck(self, cids: List[CardID], did: int) -> None:
|
||||||
self.col.db.execute(
|
self.col.db.execute(
|
||||||
f"update cards set did=?,usn=?,mod=? where id in {ids2str(cids)}",
|
f"update cards set did=?,usn=?,mod=? where id in {ids2str(cids)}",
|
||||||
did,
|
did,
|
||||||
@ -414,7 +415,7 @@ class DeckManager:
|
|||||||
intTime(),
|
intTime(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def cids(self, did: int, children: bool = False) -> List[int]:
|
def cids(self, did: int, children: bool = False) -> List[CardID]:
|
||||||
if not children:
|
if not children:
|
||||||
return self.col.db.list("select id from cards where did=?", did)
|
return self.col.db.list("select id from cards where did=?", did)
|
||||||
dids = [did]
|
dids = [did]
|
||||||
@ -422,7 +423,7 @@ class DeckManager:
|
|||||||
dids.append(id)
|
dids.append(id)
|
||||||
return self.col.db.list(f"select id from cards where did in {ids2str(dids)}")
|
return self.col.db.list(f"select id from cards where did in {ids2str(dids)}")
|
||||||
|
|
||||||
def for_card_ids(self, cids: List[int]) -> List[int]:
|
def for_card_ids(self, cids: List[CardID]) -> List[int]:
|
||||||
return self.col.db.list(f"select did from cards where id in {ids2str(cids)}")
|
return self.col.db.list(f"select did from cards where id in {ids2str(cids)}")
|
||||||
|
|
||||||
# Deck selection
|
# Deck selection
|
||||||
|
@ -12,6 +12,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union
|
|||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
from anki.cards import CardID
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
from anki.lang import TR
|
from anki.lang import TR
|
||||||
from anki.utils import ids2str, namedtmp, splitFields, stripHTML
|
from anki.utils import ids2str, namedtmp, splitFields, stripHTML
|
||||||
@ -28,7 +29,7 @@ class Exporter:
|
|||||||
self,
|
self,
|
||||||
col: Collection,
|
col: Collection,
|
||||||
did: Optional[int] = None,
|
did: Optional[int] = None,
|
||||||
cids: Optional[List[int]] = None,
|
cids: Optional[List[CardID]] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.col = col.weakref()
|
self.col = col.weakref()
|
||||||
self.did = did
|
self.did = did
|
||||||
|
@ -5,6 +5,7 @@ import os
|
|||||||
import unicodedata
|
import unicodedata
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
|
from anki.cards import CardID
|
||||||
from anki.collection import Collection
|
from anki.collection import Collection
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.decks import DeckManager
|
from anki.decks import DeckManager
|
||||||
@ -306,7 +307,7 @@ class Anki2Importer(Importer):
|
|||||||
if self.source_needs_upgrade:
|
if self.source_needs_upgrade:
|
||||||
self.src.upgrade_to_v2_scheduler()
|
self.src.upgrade_to_v2_scheduler()
|
||||||
# build map of (guid, ord) -> cid and used id cache
|
# build map of (guid, ord) -> cid and used id cache
|
||||||
self._cards: Dict[Tuple[str, int], int] = {}
|
self._cards: Dict[Tuple[str, int], CardID] = {}
|
||||||
existing = {}
|
existing = {}
|
||||||
for guid, ord, cid in self.dst.db.execute(
|
for guid, ord, cid in self.dst.db.execute(
|
||||||
"select f.guid, c.ord, c.id from cards c, notes f " "where c.nid = f.id"
|
"select f.guid, c.ord, c.id from cards c, notes f " "where c.nid = f.id"
|
||||||
|
@ -24,6 +24,7 @@ class Note:
|
|||||||
# not currently exposed
|
# not currently exposed
|
||||||
flags = 0
|
flags = 0
|
||||||
data = ""
|
data = ""
|
||||||
|
id: NoteID
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -122,7 +123,7 @@ class Note:
|
|||||||
def cards(self) -> List[anki.cards.Card]:
|
def cards(self) -> List[anki.cards.Card]:
|
||||||
return [self.col.getCard(id) for id in self.card_ids()]
|
return [self.col.getCard(id) for id in self.card_ids()]
|
||||||
|
|
||||||
def card_ids(self) -> Sequence[int]:
|
def card_ids(self) -> Sequence[anki.cards.CardID]:
|
||||||
return self.col.card_ids_of_note(self.id)
|
return self.col.card_ids_of_note(self.id)
|
||||||
|
|
||||||
def model(self) -> Optional[NoteType]:
|
def model(self) -> Optional[NoteType]:
|
||||||
|
@ -13,6 +13,7 @@ SchedTimingToday = _pb.SchedTimingTodayOut
|
|||||||
|
|
||||||
from typing import List, Optional, Sequence
|
from typing import List, Optional, Sequence
|
||||||
|
|
||||||
|
from anki.cards import CardID
|
||||||
from anki.consts import CARD_TYPE_NEW, NEW_CARDS_RANDOM, QUEUE_TYPE_NEW, QUEUE_TYPE_REV
|
from anki.consts import CARD_TYPE_NEW, NEW_CARDS_RANDOM, QUEUE_TYPE_NEW, QUEUE_TYPE_REV
|
||||||
from anki.decks import DeckConfigDict, DeckID, DeckTreeNode
|
from anki.decks import DeckConfigDict, DeckID, DeckTreeNode
|
||||||
from anki.notes import Note
|
from anki.notes import Note
|
||||||
@ -107,10 +108,10 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||||||
# Suspending & burying
|
# Suspending & burying
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def unsuspend_cards(self, ids: Sequence[int]) -> OpChanges:
|
def unsuspend_cards(self, ids: Sequence[CardID]) -> OpChanges:
|
||||||
return self.col._backend.restore_buried_and_suspended_cards(ids)
|
return self.col._backend.restore_buried_and_suspended_cards(ids)
|
||||||
|
|
||||||
def unbury_cards(self, ids: List[int]) -> OpChanges:
|
def unbury_cards(self, ids: List[CardID]) -> OpChanges:
|
||||||
return self.col._backend.restore_buried_and_suspended_cards(ids)
|
return self.col._backend.restore_buried_and_suspended_cards(ids)
|
||||||
|
|
||||||
def unbury_cards_in_current_deck(
|
def unbury_cards_in_current_deck(
|
||||||
@ -119,12 +120,12 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||||||
) -> None:
|
) -> None:
|
||||||
self.col._backend.unbury_cards_in_current_deck(mode)
|
self.col._backend.unbury_cards_in_current_deck(mode)
|
||||||
|
|
||||||
def suspend_cards(self, ids: Sequence[int]) -> OpChanges:
|
def suspend_cards(self, ids: Sequence[CardID]) -> OpChanges:
|
||||||
return self.col._backend.bury_or_suspend_cards(
|
return self.col._backend.bury_or_suspend_cards(
|
||||||
card_ids=ids, mode=BuryOrSuspend.SUSPEND
|
card_ids=ids, mode=BuryOrSuspend.SUSPEND
|
||||||
)
|
)
|
||||||
|
|
||||||
def bury_cards(self, ids: Sequence[int], manual: bool = True) -> OpChanges:
|
def bury_cards(self, ids: Sequence[CardID], manual: bool = True) -> OpChanges:
|
||||||
if manual:
|
if manual:
|
||||||
mode = BuryOrSuspend.BURY_USER
|
mode = BuryOrSuspend.BURY_USER
|
||||||
else:
|
else:
|
||||||
@ -137,13 +138,13 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||||||
# Resetting/rescheduling
|
# Resetting/rescheduling
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def schedule_cards_as_new(self, card_ids: List[int]) -> OpChanges:
|
def schedule_cards_as_new(self, card_ids: List[CardID]) -> OpChanges:
|
||||||
"Put cards at the end of the new queue."
|
"Put cards at the end of the new queue."
|
||||||
return self.col._backend.schedule_cards_as_new(card_ids=card_ids, log=True)
|
return self.col._backend.schedule_cards_as_new(card_ids=card_ids, log=True)
|
||||||
|
|
||||||
def set_due_date(
|
def set_due_date(
|
||||||
self,
|
self,
|
||||||
card_ids: List[int],
|
card_ids: List[CardID],
|
||||||
days: str,
|
days: str,
|
||||||
config_key: Optional[Config.String.Key.V] = None,
|
config_key: Optional[Config.String.Key.V] = None,
|
||||||
) -> OpChanges:
|
) -> OpChanges:
|
||||||
@ -162,7 +163,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||||||
config_key=key, # type: ignore
|
config_key=key, # type: ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
def resetCards(self, ids: List[int]) -> None:
|
def resetCards(self, ids: List[CardID]) -> None:
|
||||||
"Completely reset cards for export."
|
"Completely reset cards for export."
|
||||||
sids = ids2str(ids)
|
sids = ids2str(ids)
|
||||||
assert self.col.db
|
assert self.col.db
|
||||||
@ -184,7 +185,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||||||
|
|
||||||
def reposition_new_cards(
|
def reposition_new_cards(
|
||||||
self,
|
self,
|
||||||
card_ids: Sequence[int],
|
card_ids: Sequence[CardID],
|
||||||
starting_from: int,
|
starting_from: int,
|
||||||
step_size: int,
|
step_size: int,
|
||||||
randomize: bool,
|
randomize: bool,
|
||||||
@ -223,7 +224,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l
|
|||||||
# legacy
|
# legacy
|
||||||
def sortCards(
|
def sortCards(
|
||||||
self,
|
self,
|
||||||
cids: List[int],
|
cids: List[CardID],
|
||||||
start: int = 1,
|
start: int = 1,
|
||||||
step: int = 1,
|
step: int = 1,
|
||||||
shuffle: bool = False,
|
shuffle: bool = False,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from typing import List, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
from anki.cards import Card
|
from anki.cards import Card, CardID
|
||||||
from anki.consts import CARD_TYPE_RELEARNING, QUEUE_TYPE_DAY_LEARN_RELEARN
|
from anki.consts import CARD_TYPE_RELEARNING, QUEUE_TYPE_DAY_LEARN_RELEARN
|
||||||
from anki.decks import DeckConfigDict
|
from anki.decks import DeckConfigDict
|
||||||
from anki.notes import NoteID
|
from anki.notes import NoteID
|
||||||
@ -15,7 +15,7 @@ class SchedulerBaseWithLegacy(SchedulerBase):
|
|||||||
"Legacy aliases and helpers. These will go away in the future."
|
"Legacy aliases and helpers. These will go away in the future."
|
||||||
|
|
||||||
def reschedCards(
|
def reschedCards(
|
||||||
self, card_ids: List[int], min_interval: int, max_interval: int
|
self, card_ids: List[CardID], min_interval: int, max_interval: int
|
||||||
) -> None:
|
) -> None:
|
||||||
self.set_due_date(card_ids, f"{min_interval}-{max_interval}!")
|
self.set_due_date(card_ids, f"{min_interval}-{max_interval}!")
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe
|
|||||||
self.col.usn(),
|
self.col.usn(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def remFromDyn(self, cids: List[int]) -> None:
|
def remFromDyn(self, cids: List[CardID]) -> None:
|
||||||
self.emptyDyn(None, f"id in {ids2str(cids)} and odid")
|
self.emptyDyn(None, f"id in {ids2str(cids)} and odid")
|
||||||
|
|
||||||
# used by v2 scheduler and some add-ons
|
# used by v2 scheduler and some add-ons
|
||||||
|
@ -11,7 +11,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|||||||
import anki # pylint: disable=unused-import
|
import anki # pylint: disable=unused-import
|
||||||
import anki._backend.backend_pb2 as _pb
|
import anki._backend.backend_pb2 as _pb
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
from anki.cards import Card
|
from anki.cards import Card, CardID
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.decks import DeckConfigDict, DeckDict
|
from anki.decks import DeckConfigDict, DeckDict
|
||||||
from anki.lang import FormatTimeSpan
|
from anki.lang import FormatTimeSpan
|
||||||
@ -144,7 +144,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
|||||||
|
|
||||||
def _resetNew(self) -> None:
|
def _resetNew(self) -> None:
|
||||||
self._newDids = self.col.decks.active()[:]
|
self._newDids = self.col.decks.active()[:]
|
||||||
self._newQueue: List[int] = []
|
self._newQueue: List[CardID] = []
|
||||||
self._updateNewCardRatio()
|
self._updateNewCardRatio()
|
||||||
|
|
||||||
def _fillNew(self, recursing: bool = False) -> bool:
|
def _fillNew(self, recursing: bool = False) -> bool:
|
||||||
@ -301,8 +301,8 @@ select count() from cards where did in %s and queue = {QUEUE_TYPE_PREVIEW}
|
|||||||
def _resetLrn(self) -> None:
|
def _resetLrn(self) -> None:
|
||||||
self._updateLrnCutoff(force=True)
|
self._updateLrnCutoff(force=True)
|
||||||
self._resetLrnCount()
|
self._resetLrnCount()
|
||||||
self._lrnQueue: List[Tuple[int, int]] = []
|
self._lrnQueue: List[Tuple[int, CardID]] = []
|
||||||
self._lrnDayQueue: List[int] = []
|
self._lrnDayQueue: List[CardID] = []
|
||||||
self._lrnDids = self.col.decks.active()[:]
|
self._lrnDids = self.col.decks.active()[:]
|
||||||
|
|
||||||
# sub-day learning
|
# sub-day learning
|
||||||
@ -397,7 +397,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""",
|
|||||||
return hooks.scheduler_review_limit_for_single_deck(lim, d)
|
return hooks.scheduler_review_limit_for_single_deck(lim, d)
|
||||||
|
|
||||||
def _resetRev(self) -> None:
|
def _resetRev(self) -> None:
|
||||||
self._revQueue: List[int] = []
|
self._revQueue: List[CardID] = []
|
||||||
|
|
||||||
def _fillRev(self, recursing: bool = False) -> bool:
|
def _fillRev(self, recursing: bool = False) -> bool:
|
||||||
"True if a review card can be fetched."
|
"True if a review card can be fetched."
|
||||||
@ -1072,7 +1072,7 @@ limit ?"""
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _burySiblings(self, card: Card) -> None:
|
def _burySiblings(self, card: Card) -> None:
|
||||||
toBury: List[int] = []
|
toBury: List[CardID] = []
|
||||||
nconf = self._newConf(card)
|
nconf = self._newConf(card)
|
||||||
buryNew = nconf.get("bury", True)
|
buryNew = nconf.get("bury", True)
|
||||||
rconf = self._revConf(card)
|
rconf = self._revConf(card)
|
||||||
|
@ -22,7 +22,7 @@ from typing import (
|
|||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
import aqt.forms
|
import aqt.forms
|
||||||
from anki.cards import Card
|
from anki.cards import Card, CardID
|
||||||
from anki.collection import BrowserRow, Collection, Config, OpChanges, SearchNode
|
from anki.collection import BrowserRow, Collection, Config, OpChanges, SearchNode
|
||||||
from anki.consts import *
|
from anki.consts import *
|
||||||
from anki.errors import NotFoundError
|
from anki.errors import NotFoundError
|
||||||
@ -97,7 +97,7 @@ class SearchContext:
|
|||||||
browser: Browser
|
browser: Browser
|
||||||
order: Union[bool, str] = True
|
order: Union[bool, str] = True
|
||||||
# if set, provided card ids will be used instead of the regular search
|
# if set, provided card ids will be used instead of the regular search
|
||||||
card_ids: Optional[Sequence[int]] = None
|
card_ids: Optional[Sequence[CardID]] = None
|
||||||
|
|
||||||
|
|
||||||
# Data model
|
# Data model
|
||||||
@ -170,13 +170,13 @@ class DataModel(QAbstractTableModel):
|
|||||||
self.activeCols: List[str] = self.col.get_config(
|
self.activeCols: List[str] = self.col.get_config(
|
||||||
"activeCols", ["noteFld", "template", "cardDue", "deck"]
|
"activeCols", ["noteFld", "template", "cardDue", "deck"]
|
||||||
)
|
)
|
||||||
self.cards: Sequence[int] = []
|
self.cards: Sequence[CardID] = []
|
||||||
self._rows: Dict[int, CellRow] = {}
|
self._rows: Dict[int, CellRow] = {}
|
||||||
self._last_refresh = 0.0
|
self._last_refresh = 0.0
|
||||||
# serve stale content to avoid hitting the DB?
|
# serve stale content to avoid hitting the DB?
|
||||||
self.block_updates = False
|
self.block_updates = False
|
||||||
|
|
||||||
def get_id(self, index: QModelIndex) -> int:
|
def get_id(self, index: QModelIndex) -> CardID:
|
||||||
return self.cards[index.row()]
|
return self.cards[index.row()]
|
||||||
|
|
||||||
def get_cell(self, index: QModelIndex) -> Cell:
|
def get_cell(self, index: QModelIndex) -> Cell:
|
||||||
@ -198,7 +198,7 @@ class DataModel(QAbstractTableModel):
|
|||||||
self._rows[cid] = self._fetch_row_from_backend(cid)
|
self._rows[cid] = self._fetch_row_from_backend(cid)
|
||||||
return self._rows[cid]
|
return self._rows[cid]
|
||||||
|
|
||||||
def _fetch_row_from_backend(self, cid: int) -> CellRow:
|
def _fetch_row_from_backend(self, cid: CardID) -> CellRow:
|
||||||
try:
|
try:
|
||||||
row = CellRow(*self.col.browser_row_for_card(cid))
|
row = CellRow(*self.col.browser_row_for_card(cid))
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
@ -1049,7 +1049,7 @@ QTableView {{ gridline-color: {grid} }}
|
|||||||
# Menu helpers
|
# Menu helpers
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def selected_cards(self) -> List[int]:
|
def selected_cards(self) -> List[CardID]:
|
||||||
return [
|
return [
|
||||||
self.model.cards[idx.row()]
|
self.model.cards[idx.row()]
|
||||||
for idx in self.form.tableView.selectionModel().selectedRows()
|
for idx in self.form.tableView.selectionModel().selectedRows()
|
||||||
@ -1068,7 +1068,7 @@ where id in %s"""
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def selectedNotesAsCards(self) -> List[int]:
|
def selectedNotesAsCards(self) -> List[CardID]:
|
||||||
return self.col.db.list(
|
return self.col.db.list(
|
||||||
"select id from cards where nid in (%s)"
|
"select id from cards where nid in (%s)"
|
||||||
% ",".join([str(s) for s in self.selected_notes()])
|
% ",".join([str(s) for s in self.selected_notes()])
|
||||||
@ -1590,7 +1590,7 @@ where id in %s"""
|
|||||||
def onCardList(self) -> None:
|
def onCardList(self) -> None:
|
||||||
self.form.tableView.setFocus()
|
self.form.tableView.setFocus()
|
||||||
|
|
||||||
def focusCid(self, cid: int) -> None:
|
def focusCid(self, cid: CardID) -> None:
|
||||||
try:
|
try:
|
||||||
row = list(self.model.cards).index(cid)
|
row = list(self.model.cards).index(cid)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -5,12 +5,14 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
|
|
||||||
|
from anki.cards import CardID
|
||||||
|
from anki.decks import DeckID
|
||||||
from aqt import AnkiQt
|
from aqt import AnkiQt
|
||||||
|
|
||||||
|
|
||||||
def set_card_deck(*, mw: AnkiQt, card_ids: Sequence[int], deck_id: int) -> None:
|
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))
|
mw.perform_op(lambda: mw.col.set_deck(card_ids, deck_id))
|
||||||
|
|
||||||
|
|
||||||
def set_card_flag(*, mw: AnkiQt, card_ids: Sequence[int], flag: int) -> None:
|
def set_card_flag(*, mw: AnkiQt, card_ids: Sequence[CardID], flag: int) -> None:
|
||||||
mw.perform_op(lambda: mw.col.set_user_flag_for_cards(flag, card_ids))
|
mw.perform_op(lambda: mw.col.set_user_flag_for_cards(flag, card_ids))
|
||||||
|
@ -5,9 +5,10 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
from concurrent.futures import Future
|
from concurrent.futures import Future
|
||||||
from typing import Any
|
from typing import Any, List
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
|
from anki.cards import CardID
|
||||||
from anki.collection import EmptyCardsReport
|
from anki.collection import EmptyCardsReport
|
||||||
from aqt import gui_hooks
|
from aqt import gui_hooks
|
||||||
from aqt.qt import QDialog, QDialogButtonBox, qconnect
|
from aqt.qt import QDialog, QDialogButtonBox, qconnect
|
||||||
@ -88,14 +89,14 @@ class EmptyCardsDialog(QDialog):
|
|||||||
self.mw.taskman.run_in_background(delete, on_done)
|
self.mw.taskman.run_in_background(delete, on_done)
|
||||||
|
|
||||||
def _delete_cards(self, keep_notes: bool) -> int:
|
def _delete_cards(self, keep_notes: bool) -> int:
|
||||||
to_delete = []
|
to_delete: List[CardID] = []
|
||||||
note: EmptyCardsReport.NoteWithEmptyCards
|
note: EmptyCardsReport.NoteWithEmptyCards
|
||||||
for note in self.report.notes:
|
for note in self.report.notes:
|
||||||
if keep_notes and note.will_delete_note:
|
if keep_notes and note.will_delete_note:
|
||||||
# leave first card
|
# leave first card
|
||||||
to_delete.extend(note.card_ids[1:])
|
to_delete.extend([CardID(id) for id in note.card_ids[1:]])
|
||||||
else:
|
else:
|
||||||
to_delete.extend(note.card_ids)
|
to_delete.extend([CardID(id) for id in note.card_ids])
|
||||||
|
|
||||||
self.mw.col.remove_cards_and_orphaned_notes(to_delete)
|
self.mw.col.remove_cards_and_orphaned_notes(to_delete)
|
||||||
return len(to_delete)
|
return len(to_delete)
|
||||||
|
@ -11,6 +11,7 @@ from typing import List, Optional
|
|||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
|
from anki.cards import CardID
|
||||||
from anki.exporting import Exporter, exporters
|
from anki.exporting import Exporter, exporters
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.utils import (
|
from aqt.utils import (
|
||||||
@ -29,7 +30,7 @@ class ExportDialog(QDialog):
|
|||||||
self,
|
self,
|
||||||
mw: aqt.main.AnkiQt,
|
mw: aqt.main.AnkiQt,
|
||||||
did: Optional[int] = None,
|
did: Optional[int] = None,
|
||||||
cids: Optional[List[int]] = None,
|
cids: Optional[List[CardID]] = None,
|
||||||
):
|
):
|
||||||
QDialog.__init__(self, mw, Qt.Window)
|
QDialog.__init__(self, mw, Qt.Window)
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
|
@ -13,7 +13,7 @@ from typing import Any, Callable, List, Match, Optional, Sequence, Tuple, Union
|
|||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
from anki import hooks
|
from anki import hooks
|
||||||
from anki.cards import Card
|
from anki.cards import Card, CardID
|
||||||
from anki.collection import Config, OpChanges
|
from anki.collection import Config, OpChanges
|
||||||
from anki.tags import MARKED_TAG
|
from anki.tags import MARKED_TAG
|
||||||
from anki.utils import stripHTML
|
from anki.utils import stripHTML
|
||||||
@ -74,7 +74,7 @@ class Reviewer:
|
|||||||
self.card: Optional[Card] = None
|
self.card: Optional[Card] = None
|
||||||
self.cardQueue: List[Card] = []
|
self.cardQueue: List[Card] = []
|
||||||
self.hadCardQueue = False
|
self.hadCardQueue = False
|
||||||
self._answeredIds: List[int] = []
|
self._answeredIds: List[CardID] = []
|
||||||
self._recordedAudio: Optional[str] = None
|
self._recordedAudio: Optional[str] = None
|
||||||
self.typeCorrect: str = None # web init happens before this is set
|
self.typeCorrect: str = None # web init happens before this is set
|
||||||
self.state: Optional[str] = None
|
self.state: Optional[str] = None
|
||||||
|
@ -6,6 +6,7 @@ from __future__ import annotations
|
|||||||
from typing import List, Optional, Sequence
|
from typing import List, Optional, Sequence
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
|
from anki.cards import CardID
|
||||||
from anki.collection import CARD_TYPE_NEW, Config
|
from anki.collection import CARD_TYPE_NEW, Config
|
||||||
from anki.decks import DeckID
|
from anki.decks import DeckID
|
||||||
from anki.lang import TR
|
from anki.lang import TR
|
||||||
@ -21,7 +22,7 @@ def set_due_date_dialog(
|
|||||||
*,
|
*,
|
||||||
mw: aqt.AnkiQt,
|
mw: aqt.AnkiQt,
|
||||||
parent: QWidget,
|
parent: QWidget,
|
||||||
card_ids: List[int],
|
card_ids: List[CardID],
|
||||||
config_key: Optional[Config.String.Key.V],
|
config_key: Optional[Config.String.Key.V],
|
||||||
) -> None:
|
) -> None:
|
||||||
if not card_ids:
|
if not card_ids:
|
||||||
@ -54,7 +55,7 @@ def set_due_date_dialog(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def forget_cards(*, mw: aqt.AnkiQt, parent: QWidget, card_ids: List[int]) -> None:
|
def forget_cards(*, mw: aqt.AnkiQt, parent: QWidget, card_ids: List[CardID]) -> None:
|
||||||
if not card_ids:
|
if not card_ids:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ def forget_cards(*, mw: aqt.AnkiQt, parent: QWidget, card_ids: List[int]) -> Non
|
|||||||
|
|
||||||
|
|
||||||
def reposition_new_cards_dialog(
|
def reposition_new_cards_dialog(
|
||||||
*, mw: AnkiQt, parent: QWidget, card_ids: Sequence[int]
|
*, mw: AnkiQt, parent: QWidget, card_ids: Sequence[CardID]
|
||||||
) -> None:
|
) -> None:
|
||||||
assert mw.col.db
|
assert mw.col.db
|
||||||
row = mw.col.db.first(
|
row = mw.col.db.first(
|
||||||
@ -112,7 +113,7 @@ def reposition_new_cards(
|
|||||||
*,
|
*,
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
parent: QWidget,
|
parent: QWidget,
|
||||||
card_ids: Sequence[int],
|
card_ids: Sequence[CardID],
|
||||||
starting_from: int,
|
starting_from: int,
|
||||||
step_size: int,
|
step_size: int,
|
||||||
randomize: bool,
|
randomize: bool,
|
||||||
@ -135,7 +136,7 @@ def reposition_new_cards(
|
|||||||
def suspend_cards(
|
def suspend_cards(
|
||||||
*,
|
*,
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
card_ids: Sequence[int],
|
card_ids: Sequence[CardID],
|
||||||
success: PerformOpOptionalSuccessCallback = None,
|
success: PerformOpOptionalSuccessCallback = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
mw.perform_op(lambda: mw.col.sched.suspend_cards(card_ids), success=success)
|
mw.perform_op(lambda: mw.col.sched.suspend_cards(card_ids), success=success)
|
||||||
@ -153,14 +154,14 @@ def suspend_note(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def unsuspend_cards(*, mw: AnkiQt, card_ids: Sequence[int]) -> None:
|
def unsuspend_cards(*, mw: AnkiQt, card_ids: Sequence[CardID]) -> None:
|
||||||
mw.perform_op(lambda: mw.col.sched.unsuspend_cards(card_ids))
|
mw.perform_op(lambda: mw.col.sched.unsuspend_cards(card_ids))
|
||||||
|
|
||||||
|
|
||||||
def bury_cards(
|
def bury_cards(
|
||||||
*,
|
*,
|
||||||
mw: AnkiQt,
|
mw: AnkiQt,
|
||||||
card_ids: Sequence[int],
|
card_ids: Sequence[CardID],
|
||||||
success: PerformOpOptionalSuccessCallback = None,
|
success: PerformOpOptionalSuccessCallback = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
mw.perform_op(lambda: mw.col.sched.bury_cards(card_ids), success=success)
|
mw.perform_op(lambda: mw.col.sched.bury_cards(card_ids), success=success)
|
||||||
|
Loading…
Reference in New Issue
Block a user