diff --git a/aqt/reviewer.py b/aqt/reviewer.py index 16b7b8622..72b35762e 100644 --- a/aqt/reviewer.py +++ b/aqt/reviewer.py @@ -12,6 +12,8 @@ from anki.sound import playFromText, clearAudioQueue from aqt.utils import mungeQA, getBase import aqt +# fixme: space is scrolling instead of showing the current answer + class Reviewer(object): "Manage reviews. Maintains a separate state." @@ -21,6 +23,7 @@ class Reviewer(object): self.card = None self.cardQueue = [] self.state = None + self._setupStatus() def show(self): self.mw.setKeyHandler(self._keyHandler) @@ -40,11 +43,13 @@ class Reviewer(object): clearAudioQueue() if c: self.mw.enableCardMenuItems() + self._showStatus() self._maybeEnableSound() #self.updateMarkAction() self.state = "question" self._showQuestion() else: + self._hideStatus() self.mw.disableCardMenuItems() if self.mw.deck.cardCount(): self._showCongrats() @@ -430,3 +435,87 @@ div#filler { self.state = "empty" self.switchToWelcomeScreen() self.disableCardMenuItems() + + # Status bar + ########################################################################## + + def _setupStatus(self): + self._statusWidgets = [] + sb = self.mw.form.statusbar + def addWgt(w, stretch=0): + w.setShown(False) + sb.addWidget(w, stretch) + self._statusWidgets.append(w) + def vertSep(): + spacer = QFrame() + spacer.setFrameStyle(QFrame.VLine) + spacer.setFrameShadow(QFrame.Plain) + spacer.setStyleSheet("* { color: #888; }") + return spacer + # left spacer + space = QWidget() + addWgt(space, 1) + # remaining + self.remText = QLabel() + addWgt(self.remText, 0) + # progress + addWgt(vertSep()) + class QClickableProgress(QProgressBar): + url = "http://ichi2.net/anki/wiki/ProgressBars" + def mouseReleaseEvent(self, evt): + QDesktopServices.openUrl(QUrl(self.url)) + progressBarSize = (50, 14) + self.progressBar = QClickableProgress() + self.progressBar.setFixedSize(*progressBarSize) + self.progressBar.setMaximum(100) + self.progressBar.setTextVisible(False) + if QApplication.instance().style().objectName() != "plastique": + self.plastiqueStyle = QStyleFactory.create("plastique") + self.progressBar.setStyle(self.plastiqueStyle) + addWgt(self.progressBar, 0) + + def _showStatus(self): + self._showStatusWidgets(True) + self._updateRemaining() + self._updateProgress() + + def _hideStatus(self): + self._showStatusWidgets(False) + + def _showStatusWidgets(self, shown=True): + for w in self._statusWidgets: + w.setShown(shown) + self.mw.form.statusbar.hideOrShow() + + # fixme: only show progress for reviews, and only when revs due? + # fixme: learn cards are appearing too soon + # fixme: learn cards not appearing after 30 secs + def _updateRemaining(self): + counts = list(self.mw.deck.sched.counts()) + idx = self.mw.deck.sched.countIdx(self.card) + counts[idx] = "%s" % (counts[idx]+1) + buf = _("N:%s L:%s R:%s") % tuple(counts) + space = " " * 2 + ctxt = '%s' % counts[0] + ctxt += space + '%s' % counts[1] + ctxt += space + '%s' % counts[2] + buf = _("Remaining: %s") % ctxt + self.remText.setText(buf) + + def _updateProgress(self): + p = QPalette() + p.setColor(QPalette.Base, QColor("black")) + p.setColor(QPalette.Button, QColor("black")) + perc = 50 + if perc == 0: + p.setColor(QPalette.Highlight, QColor("black")) + elif perc < 50: + p.setColor(QPalette.Highlight, QColor("#ee0000")) + elif perc < 65: + p.setColor(QPalette.Highlight, QColor("#ee7700")) + elif perc < 75: + p.setColor(QPalette.Highlight, QColor("#eeee00")) + else: + p.setColor(QPalette.Highlight, QColor("#00ee00")) + self.progressBar.setPalette(p) + self.progressBar.setValue(perc) diff --git a/aqt/status.py b/aqt/status.py deleted file mode 100644 index 64b728844..000000000 --- a/aqt/status.py +++ /dev/null @@ -1,274 +0,0 @@ -# Copyright: Damien Elmes -# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html - -from PyQt4.QtGui import * -from PyQt4.QtCore import * -import anki -import sys, time -from anki.hooks import addHook - -class QClickableLabel(QLabel): - url = "http://ichi2.net/anki/wiki/TheTimerAndShortQuestions" - def mouseReleaseEvent(self, evt): - QDesktopServices.openUrl(QUrl(self.url)) - -class QClickableProgress(QProgressBar): - url = "http://ichi2.net/anki/wiki/ProgressBars" - def mouseReleaseEvent(self, evt): - QDesktopServices.openUrl(QUrl(self.url)) - -# Status bar -########################################################################## - -class StatusView(object): - "Manage the status bar as we transition through various states." - - warnTime = 10 - - def __init__(self, parent): - return - self.main = parent - self.statusbar = parent.mainWin.statusbar - self.shown = [] - self.hideBorders() - self.setState("deckBrowser") - self.timer = None - self.timerFlashStart = 0 - self.thinkingTimer = QTimer(parent) - print "show timer" - self.thinkingTimer.start(1000) - parent.connect(self.thinkingTimer, SIGNAL("timeout()"), - self.drawTimer) - self.countTimer = QTimer(parent) - self.countTimer.start(60000) - parent.connect(self.countTimer, SIGNAL("timeout()"), - self.updateCount) - addHook("showQuestion", self.flashTimer) - - # State control - ########################################################################## - - def setState(self, state): - "Change to STATE, and update the display." - self.state = state - if self.state == "initial": - self.showDeckStatus() - elif self.state == "deckBrowser": - self.hideDeckStatus() - elif self.state in ("showQuestion", - "deckFinished", - "deckEmpty", - "studyScreen"): - self.redraw() - self.showOrHideToolbar(self.state) - - def showOrHideToolbar(self, state): - if (not self.main.config['showProgress'] and - state in ("showQuestion", "showAnswer")): - shown = False - else: - shown = True - self.progressBar.setShown(shown) - self.etaText.setShown(shown) - self.remText.setShown(shown) - self.sep1.setShown(shown) - self.sep2.setShown(shown) - # timer has a separate option - if not self.main.config['showTimer']: - shown = False - self.timer.setShown(shown) - self.sep3.setShown(shown) - self.statusbar.hideOrShow() - - # Setup and teardown - ########################################################################## - - def vertSep(self): - spacer = QFrame() - spacer.setFrameStyle(QFrame.VLine) - spacer.setFrameShadow(QFrame.Plain) - return spacer - - def showDeckStatus(self): - if self.shown: - return - progressBarSize = (50, 14) - # small spacer - self.initialSpace = QWidget() - self.addWidget(self.initialSpace, 1) - # remaining & eta - self.remText = QLabel() - self.addWidget(self.remText, 0) - self.sep1 = self.vertSep() - self.addWidget(self.sep1, 0) - self.etaText = QLabel() - self.etaText.setToolTip(_( - "

Estimated time

" - "This is how long it will take to complete the current mode " - "at your current pace.")) - self.addWidget(self.etaText, 0) - # progress&retention - self.sep2 = self.vertSep() - self.addWidget(self.sep2, 0) - self.progressBar = QClickableProgress() - self.progressBar.setFixedSize(*progressBarSize) - self.progressBar.setMaximum(100) - self.progressBar.setTextVisible(False) - if QApplication.instance().style().objectName() != "plastique": - self.plastiqueStyle = QStyleFactory.create("plastique") - self.progressBar.setStyle(self.plastiqueStyle) - self.addWidget(self.progressBar, 0) - # timer - self.sep3 = self.vertSep() - self.addWidget(self.sep3, 0) - self.timer = QClickableLabel() - self.timer.setText("00:00") - self.addWidget(self.timer) - - def addWidget(self, w, stretch=0): - self.statusbar.addWidget(w, stretch) - self.shown.append(w) - - def hideDeckStatus(self): - for w in self.shown: - self.statusbar.removeWidget(w) - w.setParent(None) - self.shown = [] - - def hideBorders(self): - "Remove the ugly borders QT places on status bar widgets." - self.statusbar.setStyleSheet("::item { border: 0; }") - - # Updating - ########################################################################## - - def redraw(self): - p = QPalette() - stats = { - 'failed': self.main.deck.failedSoonCount, - 'new': self.main.deck.newCount, - 'rev': self.main.deck.revCount, - 'new2': self.main.deck.newAvail - } - remStr = _("Remaining: ") - if self.state == "deckFinished": - remStr += "0" - elif self.state == "deckEmpty": - remStr += "0" - else: - # remaining string, bolded depending on current card - if sys.platform.startswith("linux"): - s = " " - else: - s = "  " - if not self.main.currentCard: - remStr += "%(failed1)s" + s + "%(rev1)s" + s + "%(new1)s" - else: - t = self.main.deck.cardQueue(self.main.currentCard) - if t == 0: - remStr += ("%(failed1)s" + s + - "%(rev1)s" + s + "%(new1)s") - elif t == 1: - remStr += ("%(failed1)s" + s + "%(rev1)s" + s + - "%(new1)s") - else: - remStr += ("%(failed1)s" + s + "%(rev1)s" + s + - "%(new1)s") - stats['failed1'] = '%s' % stats['failed'] - stats['rev1'] = '%s' % stats['rev'] - stats['new1'] = '%s' % stats['new'] - self.remText.setText(remStr % stats) - self.remText.setToolTip("

" +_( - "Remaining cards") + "

" + - ngettext("There is %d failed card due soon.", \ - "There are %d failed cards due soon.", \ - stats['failed']) % stats['failed'] + "
" + - ngettext("There is %d card awaiting review.", - "There are %d cards awaiting review.", \ - stats['rev']) % stats['rev'] + "
" + - ngettext("There is %d new card due today.", \ - "There are %d new cards due today.",\ - stats['new']) % stats['new'] + "

" + - ngettext("There is %d new card in total.", \ - "There are %d new cards in total.",\ - stats['new2']) % stats['new2']) - # eta - print "need eta" - self.etaText.setText(_("ETA: %(timeLeft)s")) # % stats) - # retention & progress bars - p.setColor(QPalette.Base, QColor("black")) - p.setColor(QPalette.Button, QColor("black")) - print "need yes total%" - self.setProgressColour(p, 50) #stats['dYesTotal%']) - self.progressBar.setPalette(p) - self.progressBar.setValue(50) - # tooltips - self.progressBar.setToolTip( - _("The percentage of correct answers this session.")) - if self.main.config['showTimer']: - self.drawTimer() - self.timer.setToolTip(_(""" -

Time

-Anki tracks how long you spend looking at a card.
-This time is used to calculate the ETA, but not used
-for scheduling.

-You should aim to answer each question within
-10 seconds. Click the timer to learn more.""")) - - def setProgressColour(self, palette, perc): - if perc == 0: - palette.setColor(QPalette.Highlight, QColor("black")) - elif perc < 50: - palette.setColor(QPalette.Highlight, QColor("#ee0000")) - elif perc < 65: - palette.setColor(QPalette.Highlight, QColor("#ee7700")) - elif perc < 75: - palette.setColor(QPalette.Highlight, QColor("#eeee00")) - else: - palette.setColor(QPalette.Highlight, QColor("#00ee00")) - - def drawTimer(self): - if self.main.inDbHandler: - return - if not self.main.config['showTimer']: - return - if not self.timer: - return - if self.main.deck and self.main.state in ("showQuestion", "showAnswer"): - if self.main.currentCard: - if time.time() - self.timerFlashStart < 1: - return - if not self.main.config['showCardTimer']: - return - t = self.main.currentCard.userTime() - self.setTimer('%02d:%02d' % (t/60, t%60)) - return - self.setTimer("00:00") - - def flashTimer(self): - if not (self.main.deck.sessionStartTime and - self.main.deck.sessionTimeLimit): # or self.main.deck.reviewEarly: - return - t = time.time() - self.main.deck.sessionStartTime - t = self.main.deck.sessionTimeLimit - t - if t < 0: - t = 0 - self.setTimer('%02d:%02d' % - (t/60, t%60)) - self.timerFlashStart = time.time() - - def updateCount(self): - if self.main.inDbHandler: - return - if not self.main.deck: - return - if self.state in ("deckFinished", "studyScreen"): - self.main.deck.updateCutoff() - self.main.deck.reset() - self.redraw() - self.main.updateTitleBar() - if self.state == "studyScreen": - self.main.updateStudyStats() - - def setTimer(self, txt): - self.timer.setText("" + txt + " ")