cloze basics

This commit is contained in:
Damien Elmes 2011-04-03 23:50:51 +09:00
parent e0c4c9e896
commit ea515a5141
2 changed files with 41 additions and 78 deletions

View file

@ -11,7 +11,7 @@ from anki.sound import play
from anki.hooks import addHook, removeHook, runHook, runFilter from anki.hooks import addHook, removeHook, runHook, runFilter
from aqt.sound import getAudio from aqt.sound import getAudio
from aqt.webview import AnkiWebView from aqt.webview import AnkiWebView
from aqt.utils import shortcut from aqt.utils import shortcut, showInfo
import anki.js import anki.js
# fixme: add code to escape from text field # fixme: add code to escape from text field
@ -95,7 +95,16 @@ function onBlur() {
function saveField(type) { function saveField(type) {
// type is either 'focus' or 'key' // type is either 'focus' or 'key'
py.run(type + ":" + currentField.id.substring(1) + ":" + currentField.innerHTML); py.run(type + ":" + currentField.id.substring(1) + ":" + currentField.innerHTML);
} };
function cloze() {
var s = window.getSelection()
var r = s.getRangeAt(0).cloneContents();
var c = document.createElement('div');
c.appendChild(r);
var txt = c.innerHTML;
py.run("cloze:" + currentField.id.substring(1) + ":" + txt);
};
function setFields(fields) { function setFields(fields) {
var txt = ""; var txt = "";
@ -264,6 +273,33 @@ class Editor(object):
self._buttons['text_under'].setChecked(r['under']) self._buttons['text_under'].setChecked(r['under'])
self._buttons['text_super'].setChecked(r['super']) self._buttons['text_super'].setChecked(r['super'])
self._buttons['text_sub'].setChecked(r['sub']) self._buttons['text_sub'].setChecked(r['sub'])
elif str.startswith("cloze"):
(cmd, num, txt) = str.split(":", 2)
if not txt:
showInfo(_("Please select some text first."),
help="ClozeDeletion")
return
# check that the model is set up for cloze deletion
ok = False
for t in self.fact.model().templates:
if "cloze" in t['qfmt'] or "cloze" in t['afmt']:
ok = True
break
if not ok:
showInfo(_("Please add a cloze deletion model."),
help="ClozeDeletion")
return
num = int(num)
f = self.fact._fields[num]
# find the highest existing cloze
m = re.findall("\{\{c(\d+)::", f)
if m:
next = sorted([int(x) for x in m])[-1] + 1
else:
next = 1
self.fact._fields[num] = f.replace(
txt, "{{c%d::%s}}" % (next, txt))
self.loadFact()
def _loadFinished(self, w): def _loadFinished(self, w):
self._loaded = True self._loaded = True
@ -717,82 +753,9 @@ class Editor(object):
type = 0; ord = 0 type = 0; ord = 0
CardLayout(self.mw, self.fact, type=type, ord=ord, parent=self.widget) CardLayout(self.mw, self.fact, type=type, ord=ord, parent=self.widget)
# FIXME: in some future version, we should use a different delimiter, as
# [sound] et al conflicts
def onCloze(self): def onCloze(self):
src = self.focusedEdit() self.removeFormat()
if not src: self.web.eval("cloze();")
return
re1 = "\[(?:<.+?>)?.+?(:(.+?))?\](?:</.+?>)?"
re2 = "\[(?:<.+?>)?(.+?)(:.+?)?\](?:</.+?>)?"
# add brackets because selected?
cursor = src.textCursor()
oldSrc = None
if cursor.hasSelection():
oldSrc = src.toHtml()
s = cursor.selectionStart()
e = cursor.selectionEnd()
cursor.setPosition(e)
cursor.insertText("]]")
cursor.setPosition(s)
cursor.insertText("[[")
re1 = "\[" + re1 + "\]"
re2 = "\[" + re2 + "\]"
dst = None
for field in self.fact.fields:
w = self.fields[field.name][1]
if w.hasFocus():
dst = False
continue
if dst is False:
dst = w
break
if not dst:
dst = self.fields[self.fact.fields[0].name][1]
if dst == w:
return
# check if there's alredy something there
if not oldSrc:
oldSrc = src.toHtml()
oldDst = dst.toHtml()
if unicode(dst.toPlainText()):
if (self.lastCloze and
self.lastCloze[1] == oldSrc and
self.lastCloze[2] == oldDst):
src.setHtml(self.lastCloze[0])
dst.setHtml("")
self.lastCloze = None
self.saveFields()
return
else:
ui.utils.showInfo(
_("Next field must be blank."),
help="ClozeDeletion",
parent=self.widget)
return
# check if there's anything to change
if not re.search("\[.+?\]", unicode(src.toPlainText())):
ui.utils.showInfo(
_("You didn't specify anything to occlude."),
help="ClozeDeletion",
parent=self.widget)
return
# create
s = unicode(src.toHtml())
def repl(match):
exp = ""
if match.group(2):
exp = match.group(2)
return '<font color="%s"><b>[...%s]</b></font>' % (
clozeColour, exp)
new = re.sub(re1, repl, s)
old = re.sub(re2, '<font color="%s"><b>\\1</b></font>'
% clozeColour, s)
src.setHtml(new)
dst.setHtml(old)
self.lastCloze = (oldSrc, unicode(src.toHtml()),
unicode(dst.toHtml()))
self.saveFields()
def onHtmlEdit(self): def onHtmlEdit(self):
def helpRequested(): def helpRequested():

View file

@ -22,7 +22,7 @@ def showCritical(text, parent=None, help=""):
def showInfo(text, parent=None, help="", func=None): def showInfo(text, parent=None, help="", func=None):
"Show a small info window with an OK button." "Show a small info window with an OK button."
if not parent: if not parent:
parent = aqt.mw parent = aqt.mw.app.activeWindow() or aqt.mw
if not func: if not func:
func = QMessageBox.information func = QMessageBox.information
sb = QMessageBox.Ok sb = QMessageBox.Ok