mirror of
https://github.com/ankitects/anki.git
synced 2025-09-23 00:12:25 -04:00
move view.py into reviewer.py
This commit is contained in:
parent
909e8fb05c
commit
045d92238d
3 changed files with 128 additions and 172 deletions
|
@ -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,
|
||||||
|
|
148
aqt/main.py
148
aqt/main.py
|
@ -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,39 +729,7 @@ 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
|
|
||||||
(not self.config['saveOnClose'] and
|
|
||||||
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.close()
|
||||||
self.deck = None
|
self.deck = None
|
||||||
if not hideWelcome and not synced:
|
if not hideWelcome and not synced:
|
||||||
|
@ -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):
|
||||||
|
|
|
@ -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()
|
Loading…
Reference in a new issue