Merge pull request #543 from Arthur-Milchior/sort_according_to_path
Sort according to path
This commit is contained in:
commit
6ecf2ffa2c
@ -5,7 +5,6 @@ from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import json
|
||||
import operator
|
||||
import unicodedata
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
||||
|
||||
@ -127,7 +126,7 @@ class DeckManager:
|
||||
# child of an existing deck then it needs to be renamed
|
||||
deck = self.get(did)
|
||||
if "::" in deck["name"]:
|
||||
base = deck["name"].split("::")[-1]
|
||||
base = self.basename(deck["name"])
|
||||
suffix = ""
|
||||
while True:
|
||||
# find an unused name
|
||||
@ -261,15 +260,15 @@ class DeckManager:
|
||||
ontoDeckName = self.get(ontoDeckDid)["name"]
|
||||
|
||||
if ontoDeckDid is None or ontoDeckDid == "":
|
||||
if len(self._path(draggedDeckName)) > 1:
|
||||
self.rename(draggedDeck, self._basename(draggedDeckName))
|
||||
if len(self.path(draggedDeckName)) > 1:
|
||||
self.rename(draggedDeck, self.basename(draggedDeckName))
|
||||
elif self._canDragAndDrop(draggedDeckName, ontoDeckName):
|
||||
draggedDeck = self.get(draggedDeckDid)
|
||||
draggedDeckName = draggedDeck["name"]
|
||||
ontoDeckName = self.get(ontoDeckDid)["name"]
|
||||
assert ontoDeckName.strip()
|
||||
self.rename(
|
||||
draggedDeck, ontoDeckName + "::" + self._basename(draggedDeckName)
|
||||
draggedDeck, ontoDeckName + "::" + self.basename(draggedDeckName)
|
||||
)
|
||||
|
||||
def _canDragAndDrop(self, draggedDeckName: str, ontoDeckName: str) -> bool:
|
||||
@ -283,24 +282,44 @@ class DeckManager:
|
||||
return True
|
||||
|
||||
def _isParent(self, parentDeckName: str, childDeckName: str) -> Any:
|
||||
return self._path(childDeckName) == self._path(parentDeckName) + [
|
||||
self._basename(childDeckName)
|
||||
return self.path(childDeckName) == self.path(parentDeckName) + [
|
||||
self.basename(childDeckName)
|
||||
]
|
||||
|
||||
def _isAncestor(self, ancestorDeckName: str, descendantDeckName: str) -> Any:
|
||||
ancestorPath = self._path(ancestorDeckName)
|
||||
return ancestorPath == self._path(descendantDeckName)[0 : len(ancestorPath)]
|
||||
ancestorPath = self.path(ancestorDeckName)
|
||||
return ancestorPath == self.path(descendantDeckName)[0 : len(ancestorPath)]
|
||||
|
||||
def _path(self, name: str) -> Any:
|
||||
@staticmethod
|
||||
def path(name: str) -> Any:
|
||||
return name.split("::")
|
||||
|
||||
def _basename(self, name: str) -> Any:
|
||||
return self._path(name)[-1]
|
||||
_path = path
|
||||
|
||||
@classmethod
|
||||
def basename(cls, name: str) -> Any:
|
||||
return cls.path(name)[-1]
|
||||
|
||||
_basename = basename
|
||||
|
||||
@classmethod
|
||||
def immediate_parent_path(cls, name: str) -> Any:
|
||||
return cls._path(name)[:-1]
|
||||
|
||||
@classmethod
|
||||
def immediate_parent(cls, name: str) -> Any:
|
||||
pp = cls.immediate_parent_path(name)
|
||||
if pp:
|
||||
return "::".join(pp)
|
||||
|
||||
@classmethod
|
||||
def key(cls, deck: Dict[str, Any]) -> List[str]:
|
||||
return cls.path(deck["name"])
|
||||
|
||||
def _ensureParents(self, name: str) -> Any:
|
||||
"Ensure parents exist, and return name with case matching parents."
|
||||
s = ""
|
||||
path = self._path(name)
|
||||
path = self.path(name)
|
||||
if len(path) < 2:
|
||||
return name
|
||||
for p in path[:-1]:
|
||||
@ -454,7 +473,7 @@ class DeckManager:
|
||||
|
||||
def _checkDeckTree(self) -> None:
|
||||
decks = self.col.decks.all()
|
||||
decks.sort(key=operator.itemgetter("name"))
|
||||
decks.sort(key=self.key)
|
||||
names: Set[str] = set()
|
||||
|
||||
for deck in decks:
|
||||
@ -465,14 +484,14 @@ class DeckManager:
|
||||
self.save(deck)
|
||||
|
||||
# ensure no sections are blank
|
||||
if not all(deck["name"].split("::")):
|
||||
if not all(self.path(deck["name"])):
|
||||
self.col.log("fix deck with missing sections", deck["name"])
|
||||
deck["name"] = "recovered%d" % intTime(1000)
|
||||
self.save(deck)
|
||||
|
||||
# immediate parent must exist
|
||||
if "::" in deck["name"]:
|
||||
immediateParent = "::".join(deck["name"].split("::")[:-1])
|
||||
immediateParent = self.immediate_parent(deck["name"])
|
||||
if immediateParent not in names:
|
||||
self.col.log("fix deck with missing parent", deck["name"])
|
||||
self._ensureParents(deck["name"])
|
||||
@ -570,14 +589,13 @@ class DeckManager:
|
||||
childMap = {}
|
||||
|
||||
# go through all decks, sorted by name
|
||||
for deck in sorted(self.all(), key=operator.itemgetter("name")):
|
||||
for deck in sorted(self.all(), key=self.key):
|
||||
node: Dict[int, Any] = {}
|
||||
childMap[deck["id"]] = node
|
||||
|
||||
# add note to immediate parent
|
||||
parts = deck["name"].split("::")
|
||||
if len(parts) > 1:
|
||||
immediateParent = "::".join(parts[:-1])
|
||||
immediateParent = self.immediate_parent(deck["name"])
|
||||
if immediateParent is not None:
|
||||
pid = nameMap[immediateParent]["id"]
|
||||
childMap[pid][deck["id"]] = node
|
||||
|
||||
@ -587,7 +605,7 @@ class DeckManager:
|
||||
"All parents of did."
|
||||
# get parent and grandparent names
|
||||
parents: List[str] = []
|
||||
for part in self.get(did)["name"].split("::")[:-1]:
|
||||
for part in self.immediate_parent_path(self.get(did)["name"]):
|
||||
if not parents:
|
||||
parents.append(part)
|
||||
else:
|
||||
@ -605,7 +623,7 @@ class DeckManager:
|
||||
"All existing parents of name"
|
||||
if "::" not in name:
|
||||
return []
|
||||
names = name.split("::")[:-1]
|
||||
names = self.immediate_parent_path(name)
|
||||
head = []
|
||||
parents = []
|
||||
|
||||
|
@ -7,6 +7,7 @@ from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from anki.collection import _Collection
|
||||
from anki.consts import *
|
||||
from anki.decks import DeckManager
|
||||
from anki.importing.base import Importer
|
||||
from anki.lang import _
|
||||
from anki.storage import Collection
|
||||
@ -257,13 +258,13 @@ class Anki2Importer(Importer):
|
||||
name = g["name"]
|
||||
# if there's a prefix, replace the top level deck
|
||||
if self.deckPrefix:
|
||||
tmpname = "::".join(name.split("::")[1:])
|
||||
tmpname = "::".join(DeckManager.path(name)[1:])
|
||||
name = self.deckPrefix
|
||||
if tmpname:
|
||||
name += "::" + tmpname
|
||||
# manually create any parents so we can pull in descriptions
|
||||
head = ""
|
||||
for parent in name.split("::")[:-1]:
|
||||
for parent in DeckManager.immediate_parent_path(name):
|
||||
if head:
|
||||
head += "::"
|
||||
head += parent
|
||||
|
@ -14,6 +14,7 @@ import anki
|
||||
from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.consts import *
|
||||
from anki.decks import DeckManager
|
||||
from anki.schedv2 import Scheduler as V2
|
||||
from anki.utils import ids2str, intTime
|
||||
|
||||
@ -152,18 +153,11 @@ class Scheduler(V2):
|
||||
lims: Dict[str, List[int]] = {}
|
||||
data = []
|
||||
|
||||
def parent(name):
|
||||
parts = name.split("::")
|
||||
if len(parts) < 2:
|
||||
return None
|
||||
parts = parts[:-1]
|
||||
return "::".join(parts)
|
||||
|
||||
for deck in decks:
|
||||
p = parent(deck["name"])
|
||||
p = DeckManager.immediate_parent(deck["name"])
|
||||
# new
|
||||
nlim = self._deckNewLimitSingle(deck)
|
||||
if p:
|
||||
if p is not None:
|
||||
nlim = min(nlim, lims[p][0])
|
||||
new = self._newForDeck(deck["id"], nlim)
|
||||
# learning
|
||||
|
@ -16,6 +16,7 @@ import anki # pylint: disable=unused-import
|
||||
from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.consts import *
|
||||
from anki.decks import DeckManager
|
||||
from anki.lang import _
|
||||
from anki.rsbackend import FormatTimeSpanContext, SchedTimingToday
|
||||
from anki.utils import ids2str, intTime
|
||||
@ -239,19 +240,12 @@ order by due"""
|
||||
lims: Dict[str, List[int]] = {}
|
||||
data = []
|
||||
|
||||
def parent(name):
|
||||
parts = name.split("::")
|
||||
if len(parts) < 2:
|
||||
return None
|
||||
parts = parts[:-1]
|
||||
return "::".join(parts)
|
||||
|
||||
childMap = self.col.decks.childMap()
|
||||
for deck in decks:
|
||||
p = parent(deck["name"])
|
||||
p = DeckManager.immediate_parent(deck["name"])
|
||||
# new
|
||||
nlim = self._deckNewLimitSingle(deck)
|
||||
if p:
|
||||
if p is not None:
|
||||
nlim = min(nlim, lims[p][0])
|
||||
new = self._newForDeck(deck["id"], nlim)
|
||||
# learning
|
||||
@ -279,7 +273,7 @@ order by due"""
|
||||
def _groupChildren(self, grps: List[List[Any]]) -> Any:
|
||||
# first, split the group names into components
|
||||
for g in grps:
|
||||
g[0] = g[0].split("::")
|
||||
g[0] = DeckManager.path(g[0])
|
||||
# and sort based on those components
|
||||
grps.sort(key=itemgetter(0))
|
||||
# then run main function
|
||||
|
@ -34,6 +34,7 @@ from typing import Any, Dict, List, Optional, Tuple
|
||||
import anki
|
||||
from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.decks import DeckManager
|
||||
from anki.models import NoteType
|
||||
from anki.notes import Note
|
||||
from anki.rsbackend import TemplateReplacementList
|
||||
@ -153,7 +154,7 @@ def fields_for_rendering(
|
||||
fields["Tags"] = note.stringTags().strip()
|
||||
fields["Type"] = card.note_type()["name"]
|
||||
fields["Deck"] = col.decks.name(card.odid or card.did)
|
||||
fields["Subdeck"] = fields["Deck"].split("::")[-1]
|
||||
fields["Subdeck"] = DeckManager.basename(fields["Deck"])
|
||||
fields["Card"] = card.template()["name"]
|
||||
flag = card.userFlag()
|
||||
fields["CardFlag"] = flag and f"flag{flag}" or ""
|
||||
|
@ -20,6 +20,7 @@ from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.collection import _Collection
|
||||
from anki.consts import *
|
||||
from anki.decks import DeckManager
|
||||
from anki.lang import _, ngettext
|
||||
from anki.models import NoteType
|
||||
from anki.notes import Note
|
||||
@ -1302,7 +1303,7 @@ QTableView {{ gridline-color: {grid} }}
|
||||
def addDecks(parent, decks):
|
||||
for head, did, rev, lrn, new, children in decks:
|
||||
name = self.mw.col.decks.get(did)["name"]
|
||||
shortname = name.split("::")[-1]
|
||||
shortname = DeckManager.basename(name)
|
||||
if children:
|
||||
subm = parent.addMenu(shortname)
|
||||
subm.addItem(_("Filter"), self._filterFunc("deck", name))
|
||||
|
@ -3,6 +3,7 @@
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import aqt
|
||||
from anki.decks import DeckManager
|
||||
from anki.lang import _
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import *
|
||||
@ -51,7 +52,10 @@ class StudyDeck(QDialog):
|
||||
if title:
|
||||
self.setWindowTitle(title)
|
||||
if not names:
|
||||
names = sorted(self.mw.col.decks.allNames(dyn=dyn, force_default=False))
|
||||
names = sorted(
|
||||
self.mw.col.decks.allNames(dyn=dyn, force_default=False),
|
||||
key=DeckManager._path,
|
||||
)
|
||||
self.nameFunc = None
|
||||
self.origNames = names
|
||||
else:
|
||||
|
Loading…
Reference in New Issue
Block a user