mirror of
https://github.com/ankitects/anki.git
synced 2025-11-09 06:07:11 -05:00
Merge branch 'master' into editor-addbutton-convenience-function
This commit is contained in:
commit
5b0d740948
5 changed files with 27 additions and 60 deletions
|
|
@ -19,7 +19,6 @@ class Anki2Importer(Importer):
|
||||||
needMapper = False
|
needMapper = False
|
||||||
deckPrefix = None
|
deckPrefix = None
|
||||||
allowUpdate = True
|
allowUpdate = True
|
||||||
dupeOnSchemaChange = False
|
|
||||||
|
|
||||||
def run(self, media=None):
|
def run(self, media=None):
|
||||||
self._prepareFiles()
|
self._prepareFiles()
|
||||||
|
|
@ -65,9 +64,8 @@ class Anki2Importer(Importer):
|
||||||
# we may need to rewrite the guid if the model schemas don't match,
|
# we may need to rewrite the guid if the model schemas don't match,
|
||||||
# so we need to keep track of the changes for the card import stage
|
# so we need to keep track of the changes for the card import stage
|
||||||
self._changedGuids = {}
|
self._changedGuids = {}
|
||||||
# apart from upgrading from anki1 decks, we ignore updates to changed
|
# we ignore updates to changed schemas. we need to note the ignored
|
||||||
# schemas. we need to note the ignored guids, so we avoid importing
|
# guids, so we avoid importing invalid cards
|
||||||
# invalid cards
|
|
||||||
self._ignoredGuids = {}
|
self._ignoredGuids = {}
|
||||||
# iterate over source collection
|
# iterate over source collection
|
||||||
add = []
|
add = []
|
||||||
|
|
@ -149,20 +147,9 @@ class Anki2Importer(Importer):
|
||||||
note[MID] = dstMid
|
note[MID] = dstMid
|
||||||
if origGuid not in self._notes:
|
if origGuid not in self._notes:
|
||||||
return True
|
return True
|
||||||
# as the schemas differ and we already have a note with a different
|
# schema changed; don't import
|
||||||
# note type, this note needs a new guid
|
|
||||||
if not self.dupeOnSchemaChange:
|
|
||||||
self._ignoredGuids[origGuid] = True
|
self._ignoredGuids[origGuid] = True
|
||||||
return False
|
return False
|
||||||
while True:
|
|
||||||
note[GUID] = incGuid(note[GUID])
|
|
||||||
self._changedGuids[origGuid] = note[GUID]
|
|
||||||
# if we don't have an existing guid, we can add
|
|
||||||
if note[GUID] not in self._notes:
|
|
||||||
return True
|
|
||||||
# if the existing guid shares the same mid, we can reuse
|
|
||||||
if dstMid == self._notes[note[GUID]][MID]:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Models
|
# Models
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -736,7 +736,7 @@ where did in %s """ % self._limit())
|
||||||
info += _('''\
|
info += _('''\
|
||||||
A card's <i>ease</i> is the size of the next interval \
|
A card's <i>ease</i> is the size of the next interval \
|
||||||
when you answer "good" on a review.''')
|
when you answer "good" on a review.''')
|
||||||
txt = self._title(_("Cards Types"),
|
txt = self._title(_("Card Types"),
|
||||||
_("The division of cards in your deck(s)."))
|
_("The division of cards in your deck(s)."))
|
||||||
txt += "<table width=%d><tr><td>%s</td><td>%s</td></table>" % (
|
txt += "<table width=%d><tr><td>%s</td><td>%s</td></table>" % (
|
||||||
self.width,
|
self.width,
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ class Editor:
|
||||||
data64 = b''.join(base64.encodestring(data).splitlines())
|
data64 = b''.join(base64.encodestring(data).splitlines())
|
||||||
return 'data:%s;base64,%s' % (mime, data64.decode('ascii'))
|
return 'data:%s;base64,%s' % (mime, data64.decode('ascii'))
|
||||||
|
|
||||||
|
|
||||||
def addButton(self, icon, cmd, func, tip="", label="",
|
def addButton(self, icon, cmd, func, tip="", label="",
|
||||||
id=None, toggleable=False, keys=None):
|
id=None, toggleable=False, keys=None):
|
||||||
"""Assign func to bridge cmd, register shortcut, return button"""
|
"""Assign func to bridge cmd, register shortcut, return button"""
|
||||||
|
|
@ -137,11 +138,19 @@ class Editor:
|
||||||
id=id, toggleable=toggleable)
|
id=id, toggleable=toggleable)
|
||||||
return btn
|
return btn
|
||||||
|
|
||||||
def _addButton(self, icon, cmd, tip="", id=None, toggleable=False):
|
def _addButton(self, icon, cmd, tip="", label="", id=None, toggleable=False):
|
||||||
|
if icon:
|
||||||
if os.path.isabs(icon):
|
if os.path.isabs(icon):
|
||||||
iconstr = self.resourceToData(icon)
|
iconstr = self.resourceToData(icon)
|
||||||
else:
|
else:
|
||||||
iconstr = "/_anki/imgs/{}.png".format(icon)
|
iconstr = "/_anki/imgs/{}.png".format(icon)
|
||||||
|
imgelm = '''<img class=topbut src="{}">'''.format(iconstr)
|
||||||
|
else:
|
||||||
|
imgelm = ""
|
||||||
|
if label or not imgelm:
|
||||||
|
labelelm = '''<span class=blabel>{}</span>'''.format(label or cmd)
|
||||||
|
else:
|
||||||
|
labelelm = ""
|
||||||
if id:
|
if id:
|
||||||
idstr = 'id={}'.format(id)
|
idstr = 'id={}'.format(id)
|
||||||
else:
|
else:
|
||||||
|
|
@ -151,8 +160,12 @@ class Editor:
|
||||||
else:
|
else:
|
||||||
toggleScript = ''
|
toggleScript = ''
|
||||||
tip = shortcut(tip)
|
tip = shortcut(tip)
|
||||||
return '''<button tabindex=-1 {id} class=linkb type="button" title="{tip}" onclick="pycmd('{cmd}');{togglesc}return false;">
|
return ('''<button tabindex=-1 {id} class=linkb type="button" title="{tip}"'''
|
||||||
<img class=topbut src="{icon}"></button>'''.format(icon=iconstr, cmd=cmd, tip=tip, id=idstr, togglesc=toggleScript)
|
''' onclick="pycmd('{cmd}');{togglesc}return false;">'''
|
||||||
|
'''{imgelm}{labelelm}</button>'''.format(
|
||||||
|
imgelm=imgelm, cmd=cmd, tip=tip, labelelm=labelelm, id=idstr,
|
||||||
|
togglesc=toggleScript)
|
||||||
|
)
|
||||||
|
|
||||||
def setupShortcuts(self):
|
def setupShortcuts(self):
|
||||||
cuts = [
|
cuts = [
|
||||||
|
|
@ -175,7 +188,7 @@ class Editor:
|
||||||
("Ctrl+Shift+X", self.onHtmlEdit),
|
("Ctrl+Shift+X", self.onHtmlEdit),
|
||||||
("Ctrl+Shift+T", self.onFocusTags)
|
("Ctrl+Shift+T", self.onFocusTags)
|
||||||
]
|
]
|
||||||
runFilter("setupEditorShortcuts", cuts)
|
runFilter("setupEditorShortcuts", cuts, self)
|
||||||
for keys, fn in cuts:
|
for keys, fn in cuts:
|
||||||
QShortcut(QKeySequence(keys), self.widget, activated=fn)
|
QShortcut(QKeySequence(keys), self.widget, activated=fn)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,7 @@ class ExportDialog(QDialog):
|
||||||
# Get deck name and remove invalid filename characters
|
# Get deck name and remove invalid filename characters
|
||||||
deck_name = self.decks[self.frm.deck.currentIndex()]
|
deck_name = self.decks[self.frm.deck.currentIndex()]
|
||||||
deck_name = re.sub('[\\\\/?<>:*|"^]', '_', deck_name)
|
deck_name = re.sub('[\\\\/?<>:*|"^]', '_', deck_name)
|
||||||
filename = os.path.join(aqt.mw.pm.base,
|
filename = '{0}{1}'.format(deck_name, self.exporter.ext)
|
||||||
'{0}{1}'.format(deck_name, self.exporter.ext))
|
|
||||||
while 1:
|
while 1:
|
||||||
file = getSaveFile(self, _("Export"), "export",
|
file = getSaveFile(self, _("Export"), "export",
|
||||||
self.exporter.key, self.exporter.ext,
|
self.exporter.key, self.exporter.ext,
|
||||||
|
|
|
||||||
|
|
@ -75,38 +75,6 @@ def test_apkg():
|
||||||
imp.run()
|
imp.run()
|
||||||
assert len(os.listdir(tmp.media.dir())) == 2
|
assert len(os.listdir(tmp.media.dir())) == 2
|
||||||
|
|
||||||
def test_anki2_diffmodels():
|
|
||||||
# create a new empty deck
|
|
||||||
dst = getEmptyCol()
|
|
||||||
# import the 1 card version of the model
|
|
||||||
tmp = getUpgradeDeckPath("diffmodels2-1.apkg")
|
|
||||||
imp = AnkiPackageImporter(dst, tmp)
|
|
||||||
imp.dupeOnSchemaChange = True
|
|
||||||
imp.run()
|
|
||||||
before = dst.noteCount()
|
|
||||||
# repeating the process should do nothing
|
|
||||||
imp = AnkiPackageImporter(dst, tmp)
|
|
||||||
imp.dupeOnSchemaChange = True
|
|
||||||
imp.run()
|
|
||||||
assert before == dst.noteCount()
|
|
||||||
# then the 2 card version
|
|
||||||
tmp = getUpgradeDeckPath("diffmodels2-2.apkg")
|
|
||||||
imp = AnkiPackageImporter(dst, tmp)
|
|
||||||
imp.dupeOnSchemaChange = True
|
|
||||||
imp.run()
|
|
||||||
after = dst.noteCount()
|
|
||||||
# as the model schemas differ, should have been imported as new model
|
|
||||||
assert after == before + 1
|
|
||||||
# and the new model should have both cards
|
|
||||||
assert dst.cardCount() == 3
|
|
||||||
# repeating the process should do nothing
|
|
||||||
imp = AnkiPackageImporter(dst, tmp)
|
|
||||||
imp.dupeOnSchemaChange = True
|
|
||||||
imp.run()
|
|
||||||
after = dst.noteCount()
|
|
||||||
assert after == before + 1
|
|
||||||
assert dst.cardCount() == 3
|
|
||||||
|
|
||||||
def test_anki2_diffmodel_templates():
|
def test_anki2_diffmodel_templates():
|
||||||
# different from the above as this one tests only the template text being
|
# different from the above as this one tests only the template text being
|
||||||
# changed, not the number of cards/fields
|
# changed, not the number of cards/fields
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue