mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 06:52:21 -04:00
add ease buttons
This commit is contained in:
parent
e48e268ee5
commit
c09070df26
2 changed files with 126 additions and 144 deletions
63
aqt/main.py
63
aqt/main.py
|
@ -352,58 +352,17 @@ Please do not file a bug report with Anki.<br>""")
|
||||||
else:
|
else:
|
||||||
evt.ignore()
|
evt.ignore()
|
||||||
|
|
||||||
def reviewKeyHandler(self, evt):
|
# to port
|
||||||
if evt.key() in (Qt.Key_Up,Qt.Key_Down,Qt.Key_Left,Qt.Key_Right,
|
# elif self.state == "studyScreen":
|
||||||
Qt.Key_PageUp,Qt.Key_PageDown):
|
# if evt.key() in (Qt.Key_Enter,
|
||||||
mf = self.bodyView.body.page().currentFrame()
|
# Qt.Key_Return):
|
||||||
if evt.key() == Qt.Key_Up:
|
# evt.accept()
|
||||||
mf.evaluateJavaScript("window.scrollBy(0,-20)")
|
# return self.onStartReview()
|
||||||
elif evt.key() == Qt.Key_Down:
|
# elif self.state == "editCurrentFact":
|
||||||
mf.evaluateJavaScript("window.scrollBy(0,20)")
|
# if evt.key() == Qt.Key_Escape:
|
||||||
elif evt.key() == Qt.Key_Left:
|
# evt.accept()
|
||||||
mf.evaluateJavaScript("window.scrollBy(-20,0)")
|
# return self.moveToState("saveEdit")
|
||||||
elif evt.key() == Qt.Key_Right:
|
# evt.ignore()
|
||||||
mf.evaluateJavaScript("window.scrollBy(20,0)")
|
|
||||||
elif evt.key() == Qt.Key_PageUp:
|
|
||||||
mf.evaluateJavaScript("window.scrollBy(0,-%d)" %
|
|
||||||
int(0.9*self.bodyView.body.size().
|
|
||||||
height()))
|
|
||||||
elif evt.key() == Qt.Key_PageDown:
|
|
||||||
mf.evaluateJavaScript("window.scrollBy(0,%d)" %
|
|
||||||
int(0.9*self.bodyView.body.size().
|
|
||||||
height()))
|
|
||||||
evt.accept()
|
|
||||||
return
|
|
||||||
if self.state == "showQuestion":
|
|
||||||
if evt.key() in (Qt.Key_Enter,
|
|
||||||
Qt.Key_Return):
|
|
||||||
evt.accept()
|
|
||||||
return self.form.showAnswerButton.click()
|
|
||||||
elif evt.key() == Qt.Key_Space and not (
|
|
||||||
self.currentCard.cardModel.typeAnswer):
|
|
||||||
evt.accept()
|
|
||||||
return self.form.showAnswerButton.click()
|
|
||||||
elif self.state == "showAnswer":
|
|
||||||
if evt.key() == Qt.Key_Space:
|
|
||||||
key = str(self.defaultEaseButton())
|
|
||||||
else:
|
|
||||||
key = unicode(evt.text())
|
|
||||||
if key and key >= "1" and key <= "4":
|
|
||||||
# user entered a quality setting
|
|
||||||
num=int(key)
|
|
||||||
evt.accept()
|
|
||||||
return getattr(self.form, "easeButton%d" %
|
|
||||||
num).animateClick()
|
|
||||||
elif self.state == "studyScreen":
|
|
||||||
if evt.key() in (Qt.Key_Enter,
|
|
||||||
Qt.Key_Return):
|
|
||||||
evt.accept()
|
|
||||||
return self.onStartReview()
|
|
||||||
elif self.state == "editCurrentFact":
|
|
||||||
if evt.key() == Qt.Key_Escape:
|
|
||||||
evt.accept()
|
|
||||||
return self.moveToState("saveEdit")
|
|
||||||
evt.ignore()
|
|
||||||
|
|
||||||
def cardAnswered(self, quality):
|
def cardAnswered(self, quality):
|
||||||
"Reschedule current card and move back to getQuestion state."
|
"Reschedule current card and move back to getQuestion state."
|
||||||
|
|
207
aqt/reviewer.py
207
aqt/reviewer.py
|
@ -20,10 +20,11 @@ class Reviewer(object):
|
||||||
self.web = mw.web
|
self.web = mw.web
|
||||||
self.card = None
|
self.card = None
|
||||||
self.cardQueue = []
|
self.cardQueue = []
|
||||||
# self.main.connect(self.body, SIGNAL("loadFinished(bool)"),
|
self.state = None
|
||||||
# self.onLoadFinished)
|
|
||||||
|
|
||||||
def show(self):
|
def show(self):
|
||||||
|
self.mw.setKeyHandler(self._keyHandler)
|
||||||
|
self.web.setLinkHandler(self._linkHandler)
|
||||||
self._getCard()
|
self._getCard()
|
||||||
|
|
||||||
# Fetching a card
|
# Fetching a card
|
||||||
|
@ -41,6 +42,7 @@ class Reviewer(object):
|
||||||
self.mw.enableCardMenuItems()
|
self.mw.enableCardMenuItems()
|
||||||
self._maybeEnableSound()
|
self._maybeEnableSound()
|
||||||
#self.updateMarkAction()
|
#self.updateMarkAction()
|
||||||
|
self.state = "question"
|
||||||
self._showQuestion()
|
self._showQuestion()
|
||||||
else:
|
else:
|
||||||
self.mw.disableCardMenuItems()
|
self.mw.disableCardMenuItems()
|
||||||
|
@ -77,6 +79,28 @@ div.ansbut {
|
||||||
position: relative; top: 25%;
|
position: relative; top: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#easebuts {
|
||||||
|
bottom: 1em;
|
||||||
|
height: 55px;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -125px;
|
||||||
|
position: fixed;
|
||||||
|
width: 250px;
|
||||||
|
font-size: 100%;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.easebut {
|
||||||
|
width: 60px;
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
background: #eee;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
div#filler {
|
div#filler {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +117,7 @@ div#filler {
|
||||||
css = runFilter("addStyles", css)
|
css = runFilter("addStyles", css)
|
||||||
return css
|
return css
|
||||||
|
|
||||||
# Showing the question
|
# Showing the question (and preparing answer)
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
_revHtml = """
|
_revHtml = """
|
||||||
|
@ -103,15 +127,14 @@ div#filler {
|
||||||
<span id="answer" />
|
<span id="answer" />
|
||||||
%(a)s
|
%(a)s
|
||||||
</td></tr></table>
|
</td></tr></table>
|
||||||
|
%(buts)s
|
||||||
%(but)s
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function showans () {
|
function showans () {
|
||||||
$(".inv").removeClass('inv');
|
$(".inv").removeClass('inv');
|
||||||
location.hash = "answer";
|
location.hash = "answer";
|
||||||
|
$(".ansbut").hide();
|
||||||
|
$("#easebuts").show();
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$(".ansbut").focus();
|
$(".ansbut").focus();
|
||||||
});
|
});
|
||||||
|
@ -119,9 +142,11 @@ $(".ansbut").focus();
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _showQuestion(self):
|
def _showQuestion(self):
|
||||||
|
self.state = "question"
|
||||||
# fixme: timeboxing
|
# fixme: timeboxing
|
||||||
# fixme: q/a separation
|
# fixme: q/a separation
|
||||||
# fixme: prevent audio from repeating
|
# fixme: prevent audio from repeating
|
||||||
|
# fixme: include placeholder for type answer result
|
||||||
c = self.card
|
c = self.card
|
||||||
# original question with sounds
|
# original question with sounds
|
||||||
q = c.q()
|
q = c.q()
|
||||||
|
@ -130,118 +155,110 @@ $(".ansbut").focus();
|
||||||
self.mw.config['autoplaySounds']):
|
self.mw.config['autoplaySounds']):
|
||||||
playFromText(q)
|
playFromText(q)
|
||||||
# render
|
# render
|
||||||
|
|
||||||
|
# buf = self.typeAnsResult()
|
||||||
buf = self._revHtml % dict(
|
buf = self._revHtml % dict(
|
||||||
q=mungeQA(q),
|
q=mungeQA(q),
|
||||||
a=mungeQA(a) + '<div id=filler></div>',
|
a=mungeQA(a) + '<div id=filler></div>',
|
||||||
but=self._questionButtons())
|
buts=self._reviewButtons())
|
||||||
|
buf = self.mw.deck.media.escapeImages(buf)
|
||||||
self.web.stdHtml(buf, self._styles(), bodyClass=c.cssClass())
|
self.web.stdHtml(buf, self._styles(), bodyClass=c.cssClass())
|
||||||
|
|
||||||
runHook('showQuestion')
|
runHook('showQuestion')
|
||||||
|
|
||||||
# Question buttons
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
def _questionButtons(self):
|
|
||||||
buf = self.typeAnsInput()
|
|
||||||
# make sure to focus
|
|
||||||
buf += """
|
|
||||||
<a id=ansbut class="but ansbut" href=ans onclick="showans();">
|
|
||||||
<div class=ansbut>%s</div>
|
|
||||||
</a>
|
|
||||||
""" % _("Show Answer")
|
|
||||||
return buf
|
|
||||||
|
|
||||||
# Showing the answer
|
# Showing the answer
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _showAnswer(self):
|
def _showAnswer(self):
|
||||||
|
self.state = "answer"
|
||||||
|
c = self.card
|
||||||
a = c.a()
|
a = c.a()
|
||||||
if self.mw.config['autoplaySounds']:
|
if self.mw.config['autoplaySounds']:
|
||||||
playFromText(a)
|
playFromText(a)
|
||||||
# render
|
# render
|
||||||
runHook('showQuestion')
|
runHook('showQuestion')
|
||||||
|
|
||||||
# buf = self.typeAnsResult()
|
# Review buttons
|
||||||
# self.write(self.center('<span id=answer />'
|
|
||||||
# + mungeQA(a)))
|
|
||||||
|
|
||||||
def onLoadFinished(self, bool):
|
|
||||||
if self.state == "showAnswer":
|
|
||||||
if self.main.config['scrollToAnswer']:
|
|
||||||
mf = self.body.page().mainFrame()
|
|
||||||
mf.evaluateJavaScript("location.hash = 'answer'")
|
|
||||||
|
|
||||||
# Answer buttons
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
def _reviewButtons(self):
|
||||||
|
# type answer area
|
||||||
|
buf = self.typeAnsInput()
|
||||||
|
# show answer button
|
||||||
|
buf += """
|
||||||
|
<a id=ansbut class="but ansbut" href=ans onclick="showans();">
|
||||||
|
<div class=ansbut>%s</div>
|
||||||
|
</a>
|
||||||
|
""" % _("Show Answer")
|
||||||
|
# ease buttons
|
||||||
|
buf += self._answerButtons()
|
||||||
|
return buf
|
||||||
|
|
||||||
def _answerButtons(self):
|
def _answerButtons(self):
|
||||||
# attach to mw.cardAnswered()
|
if self.card.queue == 2:
|
||||||
self.updateEaseButtons()
|
labels = (_("Again"), _("Hard"), _("Good"), _("Easy"))
|
||||||
self.form.buttonStack.setCurrentIndex(1)
|
green = 2
|
||||||
self.form.buttonStack.show()
|
|
||||||
self.form.buttonStack.setLayoutDirection(Qt.LeftToRight)
|
|
||||||
if self.learningButtons():
|
|
||||||
self.form.easeButton2.setText(_("Good"))
|
|
||||||
self.form.easeButton3.setText(_("Easy"))
|
|
||||||
self.form.easeButton4.setText(_("Very Easy"))
|
|
||||||
else:
|
else:
|
||||||
self.form.easeButton2.setText(_("Hard"))
|
labels = (_("Again"), _("Good"), _("Easy"))
|
||||||
self.form.easeButton3.setText(_("Good"))
|
green = 1
|
||||||
self.form.easeButton4.setText(_("Easy"))
|
times = []
|
||||||
getattr(self.form, "easeButton%d" % self.defaultEaseButton()).\
|
buttons = []
|
||||||
setFocus()
|
def but(label, i):
|
||||||
|
return '''
|
||||||
|
<a class="but easebut" href=ease%d>%s</a>''' % (i, label)
|
||||||
|
for i in range(0, len(labels)):
|
||||||
|
times.append(self._buttonTime(i, green))
|
||||||
|
buttons.append(but(labels[i], i+1))
|
||||||
|
buf = ("<table><tr><td align=center>" +
|
||||||
|
"</td><td align=center>".join(times) + "</td></tr>")
|
||||||
|
buf += "<tr><td>" + "</td><td>".join(buttons) + "</td></tr></table>"
|
||||||
|
return "<div id=easebuts>" + buf + "</div>"
|
||||||
|
return buf
|
||||||
|
|
||||||
def learningButtons(self):
|
def _buttonTime(self, i, green):
|
||||||
return not self.currentCard.successive
|
if self.mw.config['suppressEstimates']:
|
||||||
|
return ""
|
||||||
|
txt = self.mw.deck.sched.nextIvlStr(self.card, i+1, True)
|
||||||
|
if i == 0:
|
||||||
|
txt = '<span style="color: #700">%s</span>' % txt
|
||||||
|
elif i == green:
|
||||||
|
txt = '<span style="color: #070">%s</span>' % txt
|
||||||
|
txt = '<span class=time>%s</span>' % txt
|
||||||
|
return txt
|
||||||
|
|
||||||
def defaultEaseButton(self):
|
# Handlers
|
||||||
if not self.currentCard.successive:
|
############################################################
|
||||||
return 2
|
|
||||||
else:
|
|
||||||
return 3
|
|
||||||
|
|
||||||
def updateEaseButtons(self):
|
def _keyHandler(self, evt):
|
||||||
nextInts = {}
|
if self.state == "question":
|
||||||
for i in range(1, 5):
|
if evt.key() in (Qt.Key_Enter,
|
||||||
l = getattr(self.form, "easeLabel%d" % i)
|
Qt.Key_Return):
|
||||||
if self.config['suppressEstimates']:
|
evt.accept()
|
||||||
l.setText("")
|
return self.web.eval("showans();")
|
||||||
elif i == 1:
|
elif evt.key() == Qt.Key_Space and not self.typeAns():
|
||||||
txt = _("Soon")
|
evt.accept()
|
||||||
if self.config['colourTimes']:
|
return self.web.eval("showans();")
|
||||||
txt = '<span style="color: #700"><b>%s</b></span>' % txt
|
elif self.state == "answer":
|
||||||
l.setText(txt)
|
# if evt.key() == Qt.Key_Space:
|
||||||
else:
|
# key = str(self.defaultEaseButton())
|
||||||
txt = self.deck.nextIntervalStr(
|
# else:
|
||||||
self.currentCard, i)
|
# key = unicode(evt.text())
|
||||||
txt = "<b>" + txt + "</b>"
|
# if key and key >= "1" and key <= "4":
|
||||||
if i == self.defaultEaseButton() and self.config['colourTimes']:
|
# # user entered a quality setting
|
||||||
txt = '<span style="color: #070">' + txt + '</span>'
|
# num=int(key)
|
||||||
l.setText(txt)
|
# evt.accept()
|
||||||
|
# return getattr(self.form, "easeButton%d" %
|
||||||
|
# num).animateClick()
|
||||||
|
pass
|
||||||
|
evt.ignore()
|
||||||
|
|
||||||
|
def _linkHandler(self, url):
|
||||||
|
print "link", url
|
||||||
|
if url == "ans":
|
||||||
|
self._showAnswer()
|
||||||
|
|
||||||
# Font properties & output
|
# Font properties & output
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
"Write the current HTML buffer to the screen."
|
|
||||||
self.buffer = self.addStyles() + self.buffer
|
|
||||||
# hook for user css
|
|
||||||
runHook("preFlushHook")
|
|
||||||
self.buffer = '''<html><head>%s</head><body>%s</body></html>''' % (
|
|
||||||
getBase(self.main.deck, self.card), self.buffer)
|
|
||||||
#print self.buffer.encode("utf-8")
|
|
||||||
b = self.buffer
|
|
||||||
# Feeding webkit unicode can result in it not finding images, so on
|
|
||||||
# linux/osx we percent escape the image paths as utf8. On Windows the
|
|
||||||
# problem is more complicated - if we percent-escape as utf8 it fixes
|
|
||||||
# some images but breaks others. When filenames are normalized by
|
|
||||||
# dropbox they become unreadable if we escape them.
|
|
||||||
if not sys.platform.startswith("win32") and self.main.deck:
|
|
||||||
# and self.main.config['mediaLocation'] == "dropbox"):
|
|
||||||
b = self.main.deck.media.escapeImages(b)
|
|
||||||
self.body.setHtml(b)
|
|
||||||
|
|
||||||
def write(self, text):
|
def write(self, text):
|
||||||
if type(text) != types.UnicodeType:
|
if type(text) != types.UnicodeType:
|
||||||
text = unicode(text, "utf-8")
|
text = unicode(text, "utf-8")
|
||||||
|
@ -287,6 +304,10 @@ $(".ansbut").focus();
|
||||||
# else:
|
# else:
|
||||||
# return QLineEdit.keyPressEvent(self, evt)
|
# return QLineEdit.keyPressEvent(self, evt)
|
||||||
|
|
||||||
|
def typeAns(self):
|
||||||
|
"True if current card has answer typing enabled."
|
||||||
|
return self.card.template()['typeAns']
|
||||||
|
|
||||||
def typeAnsInput(self):
|
def typeAnsInput(self):
|
||||||
return ""
|
return ""
|
||||||
if self.card.cardModel.typeAnswer:
|
if self.card.cardModel.typeAnswer:
|
||||||
|
@ -372,6 +393,7 @@ $(".ansbut").focus();
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _showCongrats(self):
|
def _showCongrats(self):
|
||||||
|
self.state = "congrats"
|
||||||
self.card = None
|
self.card = None
|
||||||
self.deck.db.flush()
|
self.deck.db.flush()
|
||||||
self.hideButtons()
|
self.hideButtons()
|
||||||
|
@ -394,5 +416,6 @@ $(".ansbut").focus();
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _showEmpty(self):
|
def _showEmpty(self):
|
||||||
|
self.state = "empty"
|
||||||
self.switchToWelcomeScreen()
|
self.switchToWelcomeScreen()
|
||||||
self.disableCardMenuItems()
|
self.disableCardMenuItems()
|
||||||
|
|
Loading…
Reference in a new issue