mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 15:02:21 -04:00
Merge branch 'drag-and-drop'
This commit is contained in:
commit
1aaa81ee6f
4 changed files with 87 additions and 3 deletions
|
@ -6,6 +6,7 @@ import simplejson, copy
|
|||
from anki.utils import intTime, ids2str
|
||||
from anki.consts import *
|
||||
from anki.lang import _
|
||||
from anki.errors import DeckRenameError
|
||||
|
||||
# fixmes:
|
||||
# - make sure users can't set grad interval < 1
|
||||
|
@ -161,7 +162,7 @@ class DeckManager(object):
|
|||
"Rename deck prefix to NAME if not exists. Updates children."
|
||||
# make sure target node doesn't already exist
|
||||
if newName in self.allNames():
|
||||
raise Exception("Deck exists")
|
||||
raise DeckRenameError(_("That deck already exists."))
|
||||
# rename children
|
||||
for grp in self.all():
|
||||
if grp['name'].startswith(g['name'] + "::"):
|
||||
|
@ -174,10 +175,40 @@ class DeckManager(object):
|
|||
# finally, ensure we have parents
|
||||
self._ensureParents(newName)
|
||||
|
||||
def renameForDragAndDrop(self, draggedDeckDid, ontoDeckDid):
|
||||
draggedDeck = self.get(draggedDeckDid)
|
||||
draggedDeckName = draggedDeck['name']
|
||||
ontoDeckName = self.get(ontoDeckDid)['name']
|
||||
|
||||
if ontoDeckDid == None or ontoDeckDid == '':
|
||||
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']
|
||||
self.rename(draggedDeck, ontoDeckName + "::" + self._basename(draggedDeckName))
|
||||
|
||||
def _canDragAndDrop(self, draggedDeckName, ontoDeckName):
|
||||
return draggedDeckName <> ontoDeckName \
|
||||
and not self._isParent(ontoDeckName, draggedDeckName) \
|
||||
and not self._isAncestor(draggedDeckName, ontoDeckName)
|
||||
|
||||
def _isParent(self, parentDeckName, childDeckName):
|
||||
return self._path(childDeckName) == self._path(parentDeckName) + [ self._basename(childDeckName) ]
|
||||
|
||||
def _isAncestor(self, ancestorDeckName, descendantDeckName):
|
||||
ancestorPath = self._path(ancestorDeckName)
|
||||
return ancestorPath == self._path(descendantDeckName)[0:len(ancestorPath)]
|
||||
|
||||
def _path(self, name):
|
||||
return name.split("::")
|
||||
def _basename(self, name):
|
||||
return self._path(name)[-1]
|
||||
|
||||
def _ensureParents(self, name):
|
||||
path = name.split("::")
|
||||
s = ""
|
||||
for p in path[:-1]:
|
||||
for p in self._path(name)[:-1]:
|
||||
if not s:
|
||||
s += p
|
||||
else:
|
||||
|
|
|
@ -11,3 +11,9 @@ class AnkiError(Exception):
|
|||
if self.data:
|
||||
m += ": %s" % repr(self.data)
|
||||
return m
|
||||
|
||||
class DeckRenameError(Exception):
|
||||
def __init__(self, description):
|
||||
self.description = description
|
||||
def __str__(self):
|
||||
return "Couldn't rename deck: " + description
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -79,3 +79,49 @@ def test_rename():
|
|||
d.decks.rename(d.decks.get(id), "yo")
|
||||
for n in "yo", "yo::two", "yo::two::three":
|
||||
assert n in d.decks.allNames()
|
||||
|
||||
def test_renameForDragAndDrop():
|
||||
d = getEmptyDeck()
|
||||
|
||||
def deckNames():
|
||||
return [ name for name in sorted(d.decks.allNames()) if name <> u'Default' ]
|
||||
|
||||
languages_did = d.decks.id('Languages')
|
||||
chinese_did = d.decks.id('Chinese')
|
||||
hsk_did = d.decks.id('Chinese::HSK')
|
||||
|
||||
# Renaming also renames children
|
||||
d.decks.renameForDragAndDrop(chinese_did, languages_did)
|
||||
assert deckNames() == [ 'Languages', 'Languages::Chinese', 'Languages::Chinese::HSK' ]
|
||||
|
||||
# Dragging a deck onto itself is a no-op
|
||||
d.decks.renameForDragAndDrop(languages_did, languages_did)
|
||||
assert deckNames() == [ 'Languages', 'Languages::Chinese', 'Languages::Chinese::HSK' ]
|
||||
|
||||
# Dragging a deck onto its parent is a no-op
|
||||
d.decks.renameForDragAndDrop(hsk_did, chinese_did)
|
||||
assert deckNames() == [ 'Languages', 'Languages::Chinese', 'Languages::Chinese::HSK' ]
|
||||
|
||||
# Dragging a deck onto a descendant is a no-op
|
||||
d.decks.renameForDragAndDrop(languages_did, hsk_did)
|
||||
assert deckNames() == [ 'Languages', 'Languages::Chinese', 'Languages::Chinese::HSK' ]
|
||||
|
||||
# Can drag a grandchild onto its grandparent. It becomes a child
|
||||
d.decks.renameForDragAndDrop(hsk_did, languages_did)
|
||||
assert deckNames() == [ 'Languages', 'Languages::Chinese', 'Languages::HSK' ]
|
||||
|
||||
# Can drag a deck onto its sibling
|
||||
d.decks.renameForDragAndDrop(hsk_did, chinese_did)
|
||||
assert deckNames() == [ 'Languages', 'Languages::Chinese', 'Languages::Chinese::HSK' ]
|
||||
|
||||
# Can drag a deck back to the top level
|
||||
d.decks.renameForDragAndDrop(chinese_did, None)
|
||||
assert deckNames() == [ 'Chinese', 'Chinese::HSK', 'Languages' ]
|
||||
|
||||
# Dragging a top level deck to the top level is a no-op
|
||||
d.decks.renameForDragAndDrop(chinese_did, None)
|
||||
assert deckNames() == [ 'Chinese', 'Chinese::HSK', 'Languages' ]
|
||||
|
||||
# '' is a convenient alias for the top level DID
|
||||
d.decks.renameForDragAndDrop(hsk_did, '')
|
||||
assert deckNames() == [ 'Chinese', 'HSK', 'Languages' ]
|
||||
|
|
Loading…
Reference in a new issue