move view.py into reviewer.py

This commit is contained in:
Damien Elmes 2011-03-21 11:31:42 +09:00
parent 909e8fb05c
commit 045d92238d
3 changed files with 128 additions and 172 deletions

View file

@ -14,7 +14,6 @@ defaultConf = {
'confVer': 3, 'confVer': 3,
# remove? # remove?
'colourTimes': True, 'colourTimes': True,
'deckBrowserOrder': 0,
# too long? # too long?
'deckBrowserRefreshPeriod': 3600, 'deckBrowserRefreshPeriod': 3600,
'factEditorAdvanced': False, 'factEditorAdvanced': False,

View file

@ -77,6 +77,7 @@ class AnkiQt(QMainWindow):
self.setupAutoUpdate() self.setupAutoUpdate()
# screens # screens
self.setupDeckBrowser() self.setupDeckBrowser()
self.setupReviewer()
self.setupEditor() self.setupEditor()
self.setupStudyScreen() self.setupStudyScreen()
@ -98,18 +99,18 @@ class AnkiQt(QMainWindow):
self.disableDeckMenuItems() self.disableDeckMenuItems()
self.closeAllDeckWindows() self.closeAllDeckWindows()
self.deckBrowser.show() self.deckBrowser.show()
self.updateTitleBar()
def _deckLoadingState(self, oldState): def _deckLoadingState(self, oldState):
"Run once, when deck is loaded." "Run once, when deck is loaded."
#self.editor.deck = self.deck #self.editor.deck = self.deck
# on reset? # on reset?
#self.updateTitleBar()
runHook("deckLoading", self.deck) runHook("deckLoading", self.deck)
self.enableDeckMenuItems() self.enableDeckMenuItems()
if self.config['showStudyScreen']: if False: #self.config['showStudyScreen']:
self.moveToState("studyScreen") self.moveToState("studyScreen")
else: else:
self.moveToState("getQuestion") self.moveToState("review")
def _deckLoadedState(self, oldState): def _deckLoadedState(self, oldState):
self.currentCard = None self.currentCard = None
@ -127,70 +128,12 @@ class AnkiQt(QMainWindow):
# could reset() while in review, in study options, in empty, in deck # could reset() while in review, in study options, in empty, in deck
# finished, in editor, etc. # finished, in editor, etc.
def _deckClosingState(self, oldState): def _deckClosingState(self, oldState):
"Run once, before a deck is closed." "Run once, before a deck is closed."
runHook("deckClosing", self.deck) runHook("deckClosing", self.deck)
def _getQuestionState(self, oldState): def _reviewState(self, oldState):
# stop anything playing self.reviewer.show()
clearAudioQueue()
if self.deck.isEmpty():
return self.moveToState("deckEmpty")
else:
# timeboxing only supported using the standard scheduler
if not self.deck.finishScheduler:
if self.config['showStudyScreen']:
if not self.deck.timeboxStarted():
return self.moveToState("studyScreen")
elif self.deck.timeboxReached():
self.showToolTip(_("Session limit reached."))
self.moveToState("studyScreen")
# switch to timeboxing screen
self.form.tabWidget.setCurrentIndex(2)
return
if not self.currentCard:
self.currentCard = self.deck.getCard()
if self.currentCard:
if self.lastCard:
if self.lastCard.id == self.currentCard.id:
pass
# if self.currentCard.combinedDue > time.time():
# # if the same card is being shown and it's not
# # due yet, give up
# return self.moveToState("deckFinished")
self.enableCardMenuItems()
return self.moveToState("showQuestion")
else:
return self.moveToState("deckFinished")
def _deckEmptyState(self, oldState):
self.switchToWelcomeScreen()
self.disableCardMenuItems()
def _deckFinishedState(self, oldState):
self.currentCard = None
self.deck.db.flush()
self.hideButtons()
self.disableCardMenuItems()
self.switchToCongratsScreen()
self.form.learnMoreButton.setEnabled(
not not self.deck.newAvail)
self.startRefreshTimer()
self.bodyView.setState(state)
# focus finish button
self.form.finishButton.setFocus()
runHook('deckFinished')
def _showQuestionState(self, oldState):
# ensure cwd set to media dir
self.deck.mediaDir()
self.showAnswerButton()
self.updateMarkAction()
runHook('showQuestion')
def _showAnswerState(self, oldState):
self.showEaseButtons()
def _editCurrentFactState(self, oldState): def _editCurrentFactState(self, oldState):
if self.lastState == "editCurrentFact": if self.lastState == "editCurrentFact":
@ -786,41 +729,9 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
self.closeAllDeckWindows() self.closeAllDeckWindows()
synced = False synced = False
if self.deck is not None: if self.deck is not None:
if self.deck.modifiedSinceSave(): # save and close
if (self.deck.path is None or self.deck.close()
(not self.config['saveOnClose'] and self.deck = None
not self.config['syncOnLoad'])):
# backed in memory or autosave/sync off, must confirm
while 1:
res = aqt.unsaved.ask(parent)
if res == aqt.unsaved.save:
if self.save(required=True):
break
elif res == aqt.unsaved.cancel:
self.hideWelcome = False
return False
else:
break
# auto sync (saving automatically)
if self.config['syncOnLoad'] and self.deck.syncName:
# force save, the user may not have set passwd/etc
self.deck.save()
if self.syncDeck(False, reload=False):
synced = True
while self.deckPath:
self.app.processEvents()
time.sleep(0.1)
self.hideWelcome = False
return True
# auto save
if self.config['saveOnClose'] or self.config['syncOnLoad']:
if self.deck:
self.save()
# close if the deck wasn't already closed by a failed sync
if self.deck:
self.deck.rollback()
self.deck.close()
self.deck = None
if not hideWelcome and not synced: if not hideWelcome and not synced:
self.moveToState("noDeck") self.moveToState("noDeck")
self.hideWelcome = False self.hideWelcome = False
@ -1065,6 +976,13 @@ your deck."""))
from aqt.deckbrowser import DeckBrowser from aqt.deckbrowser import DeckBrowser
self.deckBrowser = DeckBrowser(self) self.deckBrowser = DeckBrowser(self)
# Reviewer
##########################################################################
def setupReviewer(self):
from aqt.reviewer import Reviewer
self.reviewer = Reviewer(self)
# Opening and closing the app # Opening and closing the app
########################################################################## ##########################################################################
@ -1404,28 +1322,24 @@ learnt today")
# Toolbar # Toolbar
########################################################################## ##########################################################################
def setupReviewToolbar(self):
mw.toolBar.addAction(mw.actionAddcards)
mw.toolBar.addAction(mw.actionEditCurrent)
mw.toolBar.addAction(mw.actionEditLayout)
mw.toolBar.addAction(mw.actionEditdeck)
mw.toolBar.addAction(mw.actionStudyOptions)
mw.toolBar.addAction(mw.actionGraphs)
mw.toolBar.addAction(mw.actionMarkCard)
mw.toolBar.addAction(mw.actionRepeatAudio)
mw.toolBar.addAction(mw.actionClose)
def setupToolbar(self): def setupToolbar(self):
mw = self.form frm = self.form
mw.toolBar.setIconSize(QSize(24, 24)) tb = frm.toolBar
#mw.toolBar.setIconSize(QSize(self.config['iconSize'], tb.addAction(frm.actionAddcards)
# self.config['iconSize'])) tb.addAction(frm.actionEditCurrent)
toggle = mw.toolBar.toggleViewAction() tb.addAction(frm.actionEditLayout)
tb.addAction(frm.actionEditdeck)
tb.addAction(frm.actionStudyOptions)
tb.addAction(frm.actionGraphs)
tb.addAction(frm.actionMarkCard)
tb.addAction(frm.actionRepeatAudio)
tb.addAction(frm.actionClose)
tb.setIconSize(QSize(self.config['iconSize'],
self.config['iconSize']))
toggle = tb.toggleViewAction()
toggle.setText(_("Toggle Toolbar")) toggle.setText(_("Toggle Toolbar"))
self.connect(toggle, SIGNAL("triggered()"), self.connect(toggle, SIGNAL("triggered()"),
self.onToolbarToggle) self.onToolbarToggle)
if not self.config['showToolbar']:
mw.toolBar.hide()
def onToolbarToggle(self): def onToolbarToggle(self):
tb = self.form.toolBar tb = self.form.toolBar
@ -2109,10 +2023,8 @@ This deck already exists on your computer. Overwrite the local copy?"""),
def updateTitleBar(self): def updateTitleBar(self):
"Display the current deck and card count in the titlebar." "Display the current deck and card count in the titlebar."
title=aqt.appName title=aqt.appName
if self.deck != None: if self.deck:
deckpath = self.deck.name() deckpath = self.deck.name()
if self.deck.modifiedSinceSave():
deckpath += "*"
if not self.config['showProgress']: if not self.config['showProgress']:
title = deckpath + " - " + title title = deckpath + " - " + title
else: else:
@ -2123,6 +2035,8 @@ This deck already exists on your computer. Overwrite the local copy?"""),
"cards": self.deck.cardCount, "cards": self.deck.cardCount,
"due": self.deck.failedSoonCount + self.deck.revCount "due": self.deck.failedSoonCount + self.deck.revCount
} }
else:
title += " - " + _("Decks")
self.setWindowTitle(title) self.setWindowTitle(title)
def setStatus(self, text, timeout=3000): def setStatus(self, text, timeout=3000):

View file

@ -2,37 +2,40 @@
# Copyright: Damien Elmes <anki@ichi2.net> # Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
from PyQt4.QtGui import * import time, os, stat, shutil, difflib
from PyQt4.QtCore import *
import anki, anki.utils
from anki.sound import playFromText
from anki.utils import stripHTML
from anki.hooks import runHook, runFilter
import types, time, re, os, urllib, sys, difflib
import unicodedata as ucd import unicodedata as ucd
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from anki.utils import fmtTimeSpan, stripHTML
from anki.hooks import addHook, runHook, runFilter
from anki.sound import playFromText
from aqt.utils import mungeQA, getBase from aqt.utils import mungeQA, getBase
from anki.utils import fmtTimeSpan import aqt
failedCharColour = "#FF0000" failedCharColour = "#FF0000"
passedCharColour = "#00FF00" passedCharColour = "#00FF00"
futureWarningColour = "#FF0000" futureWarningColour = "#FF0000"
# Views - define the way a user is prompted for questions, etc class Reviewer(object):
########################################################################## "Manage reviews. Maintains a separate state."
class View(object): def __init__(self, mw):
"Handle the main window update as we transition through various states." self.mw = mw
self.web = mw.web
self._state = None
# self.main.connect(self.body, SIGNAL("loadFinished(bool)"),
# self.onLoadFinished)
def __init__(self, parent, body, frame=None): def show(self):
self.main = parent self._setupToolbar()
self.body = body self._reset()
self.frame = frame
self.main.connect(self.body, SIGNAL("loadFinished(bool)"),
self.onLoadFinished)
# State control # State control
########################################################################## ##########################################################################
def _reset(self):
self.web.stdHtml("")
def setState(self, state): def setState(self, state):
"Change to STATE, and update the display." "Change to STATE, and update the display."
self.oldState = getattr(self, 'state', None) self.oldState = getattr(self, 'state', None)
@ -93,6 +96,71 @@ class View(object):
col = self.main.currentCard.cardModel.lastFontColour col = self.main.currentCard.cardModel.lastFontColour
self.write("<style>html { background: %s;}</style>" % col) self.write("<style>html { background: %s;}</style>" % col)
def _getQuestionState(self, oldState):
# stop anything playing
clearAudioQueue()
if self.deck.isEmpty():
return self.moveToState("deckEmpty")
else:
# timeboxing only supported using the standard scheduler
if not self.deck.finishScheduler:
if self.config['showStudyScreen']:
if not self.deck.timeboxStarted():
return self.moveToState("studyScreen")
elif self.deck.timeboxReached():
self.showToolTip(_("Session limit reached."))
self.moveToState("studyScreen")
# switch to timeboxing screen
self.form.tabWidget.setCurrentIndex(2)
return
if not self.currentCard:
self.currentCard = self.deck.getCard()
if self.currentCard:
if self.lastCard:
if self.lastCard.id == self.currentCard.id:
pass
# if self.currentCard.combinedDue > time.time():
# # if the same card is being shown and it's not
# # due yet, give up
# return self.moveToState("deckFinished")
self.enableCardMenuItems()
return self.moveToState("showQuestion")
else:
return self.moveToState("deckFinished")
def _deckEmptyState(self, oldState):
self.switchToWelcomeScreen()
self.disableCardMenuItems()
def _deckFinishedState(self, oldState):
self.currentCard = None
self.deck.db.flush()
self.hideButtons()
self.disableCardMenuItems()
self.switchToCongratsScreen()
self.form.learnMoreButton.setEnabled(
not not self.deck.newAvail)
self.startRefreshTimer()
self.bodyView.setState(state)
# focus finish button
self.form.finishButton.setFocus()
runHook('deckFinished')
def _showQuestionState(self, oldState):
# ensure cwd set to media dir
self.deck.mediaDir()
self.showAnswerButton()
self.updateMarkAction()
runHook('showQuestion')
def _showAnswerState(self, oldState):
self.showEaseButtons()
# Font properties & output # Font properties & output
########################################################################## ##########################################################################
@ -292,40 +360,15 @@ class View(object):
# Welcome/empty/finished deck messages # Welcome/empty/finished deck messages
########################################################################## ##########################################################################
def drawWelcomeMessage(self):
self.main.mainWin.welcomeText.setText("""\
<h1>%(welcome)s</h1>
<p>
<table>
<tr>
<td width=50>
<a href="welcome:addfacts"><img src=":/icons/list-add.png"></a>
</td>
<td valign=middle><h1><a href="welcome:addfacts">%(add)s</a></h1>
%(start)s</td>
</tr>
</table>
<br>
<table>
<tr>
<td width=50>
<a href="welcome:back"><img src=":/icons/go-previous.png"></a>
</td>
<td valign=middle><h2><a href="welcome:back">%(back)s</a></h2></td>
</tr>
</table>""" % \
{"welcome":_("Welcome to Anki!"),
"add":_("Add Material"),
"start":_("Start adding your own material."),
"back":_("Back to Deck Browser"),
})
def drawDeckFinishedMessage(self): def drawDeckFinishedMessage(self):
"Tell the user the deck is finished." "Tell the user the deck is finished."
self.main.mainWin.congratsLabel.setText( self.main.mainWin.congratsLabel.setText(
self.main.deck.deckFinishedMsg()) self.main.deck.deckFinishedMsg())
# Toolbar
##########################################################################
def _setupToolbar(self):
if not self.mw.config['showToolbar']:
return
self.mw.form.toolBar.show()