mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 22:42:25 -04:00
move the overview into a separate file; rename noDeck state to deckBrowser
This commit is contained in:
parent
04040e60f2
commit
7604fa3797
6 changed files with 230 additions and 176 deletions
|
@ -142,7 +142,7 @@ a { font-size: 80%; }
|
||||||
def _renderPage(self):
|
def _renderPage(self):
|
||||||
if self._decks:
|
if self._decks:
|
||||||
buf = ""
|
buf = ""
|
||||||
css = self.mw._sharedCSS + self._css
|
css = self.mw.sharedCSS + self._css
|
||||||
max=len(self._decks)-1
|
max=len(self._decks)-1
|
||||||
for c, deck in enumerate(self._decks):
|
for c, deck in enumerate(self._decks):
|
||||||
buf += self._deckRow(c, max, deck)
|
buf += self._deckRow(c, max, deck)
|
||||||
|
|
119
aqt/main.py
119
aqt/main.py
|
@ -52,7 +52,7 @@ class AnkiQt(QMainWindow):
|
||||||
len(self.config['recentDeckPaths']) == 1):
|
len(self.config['recentDeckPaths']) == 1):
|
||||||
self.maybeLoadLastDeck(args)
|
self.maybeLoadLastDeck(args)
|
||||||
else:
|
else:
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
except:
|
except:
|
||||||
showInfo("Error during startup:\n%s" % traceback.format_exc())
|
showInfo("Error during startup:\n%s" % traceback.format_exc())
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -77,33 +77,21 @@ class AnkiQt(QMainWindow):
|
||||||
self.setupAutoUpdate()
|
self.setupAutoUpdate()
|
||||||
# screens
|
# screens
|
||||||
self.setupDeckBrowser()
|
self.setupDeckBrowser()
|
||||||
|
self.setupOverview()
|
||||||
self.setupReviewer()
|
self.setupReviewer()
|
||||||
self.setupEditor()
|
self.setupEditor()
|
||||||
self.setupStudyScreen()
|
self.setupStudyScreen()
|
||||||
|
|
||||||
_sharedCSS = """
|
|
||||||
body { background-color: #eee; margin-top: 1em; }
|
|
||||||
a:hover { background-color: #aaa; }
|
|
||||||
a.but { font-size: 80%; padding: 3; background-color: #ccc;
|
|
||||||
border-radius: 2px; color: #000; margin: 0 5 0 5; text-decoration:
|
|
||||||
none; display: inline-block; }
|
|
||||||
h1 { margin-bottom: 0.2em; }
|
|
||||||
hr { margin:5 0 5 0; border:0; height:1px; background-color:#ddd; }
|
|
||||||
"""
|
|
||||||
#a { text-decoration: none; }
|
|
||||||
|
|
||||||
# State machine
|
# State machine
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def moveToState(self, state, *args):
|
def moveToState(self, state, *args):
|
||||||
# eg noDeck -> noDeckState(oldState)
|
|
||||||
print "-> move from", self.state, "to", state
|
print "-> move from", self.state, "to", state
|
||||||
getattr(self, "_"+state+"State")(self.state, *args)
|
|
||||||
self.state = state
|
self.state = state
|
||||||
|
getattr(self, "_"+state+"State")(self.state, *args)
|
||||||
|
|
||||||
def _noDeckState(self, oldState):
|
def _deckBrowserState(self, oldState):
|
||||||
"Run when a deck is closed, or we open with an empty deck."
|
# shouldn't call this directly; call close
|
||||||
# blank menus and load deck browser
|
|
||||||
self.deck = None
|
self.deck = None
|
||||||
self.currentCard = None
|
self.currentCard = None
|
||||||
self.lastCard = None
|
self.lastCard = None
|
||||||
|
@ -114,35 +102,17 @@ hr { margin:5 0 5 0; border:0; height:1px; background-color:#ddd; }
|
||||||
|
|
||||||
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
|
|
||||||
# on reset?
|
|
||||||
runHook("deckLoading", self.deck)
|
runHook("deckLoading", self.deck)
|
||||||
self.enableDeckMenuItems()
|
self.enableDeckMenuItems()
|
||||||
if False: #self.config['showStudyScreen']:
|
self.moveToState("overview")
|
||||||
self.moveToState("studyScreen")
|
|
||||||
else:
|
|
||||||
self.moveToState("review")
|
|
||||||
|
|
||||||
def _deckLoadedState(self, oldState):
|
|
||||||
self.currentCard = None
|
|
||||||
self.lastCard = None
|
|
||||||
# to make programming easy, reset to reviews is fastest
|
|
||||||
# but users expect edit windows to stay open. instead, we give each
|
|
||||||
# module some hooks to respond to:
|
|
||||||
# reset: called when we have modified the database and need to check
|
|
||||||
# if things are still valid. edit windows should pull their data from
|
|
||||||
# the database and close if the card/fact no longer exists. add window
|
|
||||||
# doesn't have to do anything. editor.. what to do about the editor?
|
|
||||||
# close: most windows will want to respond and close as there's no
|
|
||||||
# longer a deck. we probably want to make thing like the graphs not
|
|
||||||
# modal too.
|
|
||||||
# could reset() while in review, in study options, in empty, in deck
|
|
||||||
# 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 _overviewState(self, oldState):
|
||||||
|
self.overview.show()
|
||||||
|
|
||||||
def _reviewState(self, oldState):
|
def _reviewState(self, oldState):
|
||||||
self.reviewer.show()
|
self.reviewer.show()
|
||||||
|
|
||||||
|
@ -176,6 +146,29 @@ hr { margin:5 0 5 0; border:0; height:1px; background-color:#ddd; }
|
||||||
runHook("guiReset")
|
runHook("guiReset")
|
||||||
self.moveToState("initial")
|
self.moveToState("initial")
|
||||||
|
|
||||||
|
|
||||||
|
# HTML helpers
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
sharedCSS = """
|
||||||
|
body { background-color: #eee; margin-top: 1em; }
|
||||||
|
a:hover { background-color: #aaa; }
|
||||||
|
a.but { font-size: 80%; padding: 3; background-color: #ccc;
|
||||||
|
border-radius: 2px; color: #000; margin: 0 5 0 5; text-decoration:
|
||||||
|
none; display: inline-block; }
|
||||||
|
a.but:focus { background-color: #aaa; }
|
||||||
|
h1 { margin-bottom: 0.2em; }
|
||||||
|
hr { margin:5 0 5 0; border:0; height:1px; background-color:#ddd; }
|
||||||
|
"""
|
||||||
|
|
||||||
|
def button(self, link, name, key=None):
|
||||||
|
if key:
|
||||||
|
key = _("Shortcut key: %s") % key
|
||||||
|
else:
|
||||||
|
key = ""
|
||||||
|
return '<a class=but title="%s" href="%s">%s</a>' % (
|
||||||
|
key, link, name)
|
||||||
|
|
||||||
# Signal handling
|
# Signal handling
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
@ -649,7 +642,7 @@ counts are %d %d %d
|
||||||
aqt.utils.showCritical(_("""\
|
aqt.utils.showCritical(_("""\
|
||||||
File is corrupt or not an Anki database. Click help for more info.\n
|
File is corrupt or not an Anki database. Click help for more info.\n
|
||||||
Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
return 0
|
return 0
|
||||||
self.config.addRecentDeck(self.deck.path)
|
self.config.addRecentDeck(self.deck.path)
|
||||||
self.setupMedia(self.deck)
|
self.setupMedia(self.deck)
|
||||||
|
@ -724,13 +717,12 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def onClose(self):
|
def onClose(self):
|
||||||
# allow focusOut to save
|
|
||||||
if self.inMainWindow() or not self.app.activeWindow():
|
if self.inMainWindow() or not self.app.activeWindow():
|
||||||
self.saveAndClose()
|
self.close()
|
||||||
else:
|
else:
|
||||||
self.app.activeWindow().close()
|
self.app.activeWindow().close()
|
||||||
|
|
||||||
def saveAndClose(self, hideWelcome=False, parent=None):
|
def close(self, hideWelcome=False, parent=None):
|
||||||
"(Auto)save and close. Prompt if necessary. True if okay to proceed."
|
"(Auto)save and close. Prompt if necessary. True if okay to proceed."
|
||||||
# allow any focusOut()s to run first
|
# allow any focusOut()s to run first
|
||||||
self.setFocus()
|
self.setFocus()
|
||||||
|
@ -744,7 +736,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
||||||
self.deck.close()
|
self.deck.close()
|
||||||
self.deck = None
|
self.deck = None
|
||||||
if not hideWelcome and not synced:
|
if not hideWelcome and not synced:
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
self.hideWelcome = False
|
self.hideWelcome = False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -758,7 +750,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
||||||
|
|
||||||
def onNew(self, path=None, prompt=None):
|
def onNew(self, path=None, prompt=None):
|
||||||
if not self.inMainWindow() and not path: return
|
if not self.inMainWindow() and not path: return
|
||||||
if not self.saveAndClose(hideWelcome=True): return
|
self.close()
|
||||||
register = not path
|
register = not path
|
||||||
bad = ":/\\"
|
bad = ":/\\"
|
||||||
name = _("mydeck")
|
name = _("mydeck")
|
||||||
|
@ -769,7 +761,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
||||||
name = aqt.utils.getOnlyText(
|
name = aqt.utils.getOnlyText(
|
||||||
prompt, default=name, title=_("New Deck"))
|
prompt, default=name, title=_("New Deck"))
|
||||||
if not name:
|
if not name:
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
return
|
return
|
||||||
found = False
|
found = False
|
||||||
for c in bad:
|
for c in bad:
|
||||||
|
@ -789,7 +781,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
||||||
defaultno=True):
|
defaultno=True):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
else:
|
else:
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
return
|
return
|
||||||
self.deck = DeckStorage.Deck(path)
|
self.deck = DeckStorage.Deck(path)
|
||||||
self.deck.initUndo()
|
self.deck.initUndo()
|
||||||
|
@ -834,7 +826,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
||||||
def onOpenOnline(self):
|
def onOpenOnline(self):
|
||||||
if not self.inMainWindow(): return
|
if not self.inMainWindow(): return
|
||||||
self.ensureSyncParams()
|
self.ensureSyncParams()
|
||||||
if not self.saveAndClose(hideWelcome=True): return
|
self.close()
|
||||||
# we need a disk-backed file for syncing
|
# we need a disk-backed file for syncing
|
||||||
dir = unicode(tempfile.mkdtemp(prefix="anki"), sys.getfilesystemencoding())
|
dir = unicode(tempfile.mkdtemp(prefix="anki"), sys.getfilesystemencoding())
|
||||||
path = os.path.join(dir, u"untitled.anki")
|
path = os.path.join(dir, u"untitled.anki")
|
||||||
|
@ -980,15 +972,16 @@ your deck."""))
|
||||||
self.moveToState("initial")
|
self.moveToState("initial")
|
||||||
return file
|
return file
|
||||||
|
|
||||||
# Deck browser
|
# Components
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def setupDeckBrowser(self):
|
def setupDeckBrowser(self):
|
||||||
from aqt.deckbrowser import DeckBrowser
|
from aqt.deckbrowser import DeckBrowser
|
||||||
self.deckBrowser = DeckBrowser(self)
|
self.deckBrowser = DeckBrowser(self)
|
||||||
|
|
||||||
# Reviewer
|
def setupOverview(self):
|
||||||
##########################################################################
|
from aqt.overview import Overview
|
||||||
|
self.overview = Overview(self)
|
||||||
|
|
||||||
def setupReviewer(self):
|
def setupReviewer(self):
|
||||||
from aqt.reviewer import Reviewer
|
from aqt.reviewer import Reviewer
|
||||||
|
@ -1014,15 +1007,13 @@ your deck."""))
|
||||||
if self.state == "editCurrentFact":
|
if self.state == "editCurrentFact":
|
||||||
event.ignore()
|
event.ignore()
|
||||||
return self.moveToState("saveEdit")
|
return self.moveToState("saveEdit")
|
||||||
if not self.saveAndClose(hideWelcome=True):
|
self.close()
|
||||||
event.ignore()
|
if self.config['syncOnProgramOpen']:
|
||||||
else:
|
self.hideWelcome = True
|
||||||
if self.config['syncOnProgramOpen']:
|
self.syncDeck(interactive=False)
|
||||||
self.hideWelcome = True
|
self.prepareForExit()
|
||||||
self.syncDeck(interactive=False)
|
event.accept()
|
||||||
self.prepareForExit()
|
self.app.quit()
|
||||||
event.accept()
|
|
||||||
self.app.quit()
|
|
||||||
|
|
||||||
# Edit current fact
|
# Edit current fact
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
@ -1822,7 +1813,7 @@ Are you sure?""" % deckName),
|
||||||
if self.loadAfterSync == -1:
|
if self.loadAfterSync == -1:
|
||||||
# after sync all, so refresh browser list
|
# after sync all, so refresh browser list
|
||||||
self.browserLastRefreshed = 0
|
self.browserLastRefreshed = 0
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
elif self.loadAfterSync and self.deckPath:
|
elif self.loadAfterSync and self.deckPath:
|
||||||
if self.loadAfterSync == 2:
|
if self.loadAfterSync == 2:
|
||||||
name = re.sub("[<>]", "", self.syncName)
|
name = re.sub("[<>]", "", self.syncName)
|
||||||
|
@ -1849,9 +1840,9 @@ Are you sure?""" % deckName),
|
||||||
c.close()
|
c.close()
|
||||||
self.loadDeck(self.deckPath)
|
self.loadDeck(self.deckPath)
|
||||||
else:
|
else:
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
except:
|
except:
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
self.deckPath = None
|
self.deckPath = None
|
||||||
|
@ -1883,7 +1874,7 @@ This deck already exists on your computer. Overwrite the local copy?"""),
|
||||||
"Unload a new deck if an initial sync failed."
|
"Unload a new deck if an initial sync failed."
|
||||||
self.deck = None
|
self.deck = None
|
||||||
self.deckPath = None
|
self.deckPath = None
|
||||||
self.moveToState("noDeck")
|
self.moveToState("deckBrowser")
|
||||||
self.syncFinished = True
|
self.syncFinished = True
|
||||||
|
|
||||||
def setSyncStatus(self, text, *args):
|
def setSyncStatus(self, text, *args):
|
||||||
|
|
168
aqt/overview.py
Normal file
168
aqt/overview.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||||
|
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
|
||||||
|
|
||||||
|
import simplejson
|
||||||
|
from PyQt4.QtCore import *
|
||||||
|
from PyQt4.QtGui import *
|
||||||
|
from anki.consts import NEW_CARDS_RANDOM
|
||||||
|
|
||||||
|
class Overview(object):
|
||||||
|
"Deck overview."
|
||||||
|
|
||||||
|
def __init__(self, mw):
|
||||||
|
self.mw = mw
|
||||||
|
self.web = mw.web
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
self._setupToolbar()
|
||||||
|
self.mw.setKeyHandler(self._keyHandler)
|
||||||
|
self.web.setLinkHandler(self._linkHandler)
|
||||||
|
self._renderPage()
|
||||||
|
|
||||||
|
# Handlers
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
def _keyHandler(self, evt):
|
||||||
|
txt = evt.text()
|
||||||
|
if txt == "1":
|
||||||
|
self._linkHandler("studysel")
|
||||||
|
elif txt == "2":
|
||||||
|
self._linkHandler("studyall")
|
||||||
|
elif txt == "3":
|
||||||
|
self._linkHandler("cramsel")
|
||||||
|
elif txt == "4":
|
||||||
|
self._linkHandler("cramall")
|
||||||
|
elif txt == "o":
|
||||||
|
self._linkHandler("opts")
|
||||||
|
elif txt == "d":
|
||||||
|
self._linkHandler("list")
|
||||||
|
else:
|
||||||
|
evt.ignore()
|
||||||
|
return
|
||||||
|
evt.accept()
|
||||||
|
|
||||||
|
def _linkHandler(self, url):
|
||||||
|
if url == "studysel":
|
||||||
|
pass
|
||||||
|
elif url == "opts":
|
||||||
|
pass
|
||||||
|
elif url == "list":
|
||||||
|
self.mw.close()
|
||||||
|
|
||||||
|
# HTML
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
def _renderPage(self):
|
||||||
|
css = self.mw.sharedCSS + self._overviewCSS
|
||||||
|
fc = self._ovForecast()
|
||||||
|
tbl = self._overviewTable()
|
||||||
|
self.web.stdHtml(self._overviewBody % dict(
|
||||||
|
title=_("Overview"),
|
||||||
|
table=tbl,
|
||||||
|
fcsub=_("Due over next two weeks"),
|
||||||
|
fcdata=fc,
|
||||||
|
opts=self._ovOpts(),
|
||||||
|
), css)
|
||||||
|
|
||||||
|
_overviewBody = """
|
||||||
|
<center>
|
||||||
|
<h1>%(title)s</h1>
|
||||||
|
%(table)s
|
||||||
|
<hr>
|
||||||
|
<div id="placeholder" style="width:350px; height:100px;"></div>
|
||||||
|
<span class=sub>%(fcsub)s</span>
|
||||||
|
<hr class=sub>
|
||||||
|
%(opts)s
|
||||||
|
</center>
|
||||||
|
|
||||||
|
<script id="source" language="javascript" type="text/javascript">
|
||||||
|
$(function () {
|
||||||
|
var d = %(fcdata)s;
|
||||||
|
if (d) {
|
||||||
|
$.plot($("#placeholder"), [
|
||||||
|
{ data: d, bars: { show: true, barWidth: 0.8 } }
|
||||||
|
], {
|
||||||
|
xaxis: { ticks: [[0.4, "Today"]] }
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$("#placeholder").hide();
|
||||||
|
$(".sub").hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
"""
|
||||||
|
|
||||||
|
_overviewCSS = """
|
||||||
|
.due { text-align: right; color: green; }
|
||||||
|
.new { text-align: right; color: blue; }
|
||||||
|
.sub { font-size: 80%; color: #555; }
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _overviewTable(self):
|
||||||
|
counts = self._ovCounts()
|
||||||
|
but = self.mw.button
|
||||||
|
buf = "<table cellspacing=0 cellpadding=3 width=400>"
|
||||||
|
buf += "<tr><th></th><th align=right>%s</th>" % _("Due")
|
||||||
|
buf += "<th align=right>%s</th><th></th></tr>" % _("New")
|
||||||
|
line = "<tr><td><b>%s</b></td><td class=due>%s</td>"
|
||||||
|
line += "<td class=new>%s</td><td align=right>%s</td></tr>"
|
||||||
|
buf += line % (
|
||||||
|
"<a href=chgrp>%s</a>" % _("Selected Groups"),
|
||||||
|
counts[0], counts[1],
|
||||||
|
but("studysel", _("Study"), "1") +
|
||||||
|
but("cramsel", _("Cram"), "3"))
|
||||||
|
buf += line % (
|
||||||
|
_("Whole Deck"),
|
||||||
|
counts[2], counts[3],
|
||||||
|
but("studyall", _("Study"), "2") +
|
||||||
|
but("cramall", _("Cram"), "4"))
|
||||||
|
buf += "</table>"
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def _ovOpts(self):
|
||||||
|
if self.mw.deck.qconf['newCardOrder'] == NEW_CARDS_RANDOM:
|
||||||
|
ord = _("random")
|
||||||
|
else:
|
||||||
|
ord = _("order added")
|
||||||
|
but = self.mw.button
|
||||||
|
buf = """
|
||||||
|
<table width=400>
|
||||||
|
<tr><td><b>%s</b></td><td align=center>%s</td><td align=right rowspan=1>%s</td></tr>
|
||||||
|
<tr><td><b>%s</b></td><td align=center>%s</td><td align=right rowspan=1>%s</td></tr>
|
||||||
|
</table>""" % (
|
||||||
|
_("New cards per day"), self.mw.deck.qconf['newPerDay'],
|
||||||
|
but("opts", _("Study Options"), "o"),
|
||||||
|
_("New card order"), ord,
|
||||||
|
but("list", "◀"+_("Deck List"), "d"))
|
||||||
|
return buf
|
||||||
|
|
||||||
|
# Data
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
def _ovCounts(self):
|
||||||
|
oldNew = self.mw.deck.qconf['newGroups']
|
||||||
|
oldRev = self.mw.deck.qconf['revGroups']
|
||||||
|
# we have the limited count already
|
||||||
|
selcnt = self.mw.deck.sched.selCounts()
|
||||||
|
allcnt = self.mw.deck.sched.allCounts()
|
||||||
|
return [
|
||||||
|
selcnt[1] + selcnt[2],
|
||||||
|
selcnt[0],
|
||||||
|
allcnt[1] + allcnt[2],
|
||||||
|
allcnt[0],
|
||||||
|
]
|
||||||
|
|
||||||
|
def _ovForecast(self):
|
||||||
|
fc = self.mw.deck.sched.dueForecast(14)
|
||||||
|
if not sum(fc):
|
||||||
|
return "''"
|
||||||
|
return simplejson.dumps(tuple(enumerate(fc)))
|
||||||
|
|
||||||
|
# Toolbar
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
def _setupToolbar(self):
|
||||||
|
if not self.mw.config['showToolbar']:
|
||||||
|
return
|
||||||
|
self.mw.form.toolBar.show()
|
|
@ -83,7 +83,7 @@ class Preferences(QDialog):
|
||||||
self.origConfig.save()
|
self.origConfig.save()
|
||||||
self.parent.setLang()
|
self.parent.setLang()
|
||||||
if self.needDeckClose:
|
if self.needDeckClose:
|
||||||
self.parent.saveAndClose(parent=self)
|
self.parent.close(parent=self)
|
||||||
else:
|
else:
|
||||||
self.parent.reset()
|
self.parent.reset()
|
||||||
self.done(0)
|
self.done(0)
|
||||||
|
|
111
aqt/reviewer.py
111
aqt/reviewer.py
|
@ -31,116 +31,11 @@ class Reviewer(object):
|
||||||
self._setupToolbar()
|
self._setupToolbar()
|
||||||
self._reset()
|
self._reset()
|
||||||
|
|
||||||
# Overview state
|
|
||||||
##########################################################################
|
|
||||||
|
|
||||||
_overviewBody = """
|
|
||||||
<center>
|
|
||||||
<h1>%(title)s</h1>
|
|
||||||
%(table)s
|
|
||||||
<hr>
|
|
||||||
<div id="placeholder" style="width:350px; height:100px;"></div>
|
|
||||||
<span class=sub>%(fcsub)s</span>
|
|
||||||
<hr class=sub>
|
|
||||||
%(opts)s
|
|
||||||
</center>
|
|
||||||
|
|
||||||
<script id="source" language="javascript" type="text/javascript">
|
|
||||||
$(function () {
|
|
||||||
var d = %(fcdata)s;
|
|
||||||
if (d) {
|
|
||||||
$.plot($("#placeholder"), [
|
|
||||||
{ data: d, bars: { show: true, barWidth: 0.8 } }
|
|
||||||
], {
|
|
||||||
xaxis: { ticks: [[0.4, "Today"]] }
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$("#placeholder").hide();
|
|
||||||
$(".sub").hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
"""
|
|
||||||
|
|
||||||
_overviewCSS = """
|
|
||||||
.due { text-align: right; color: green; }
|
|
||||||
.new { text-align: right; color: blue; }
|
|
||||||
.sub { font-size: 80%; color: #555; }
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _overview(self):
|
|
||||||
css = self.mw._sharedCSS + self._overviewCSS
|
|
||||||
fc = self._ovForecast()
|
|
||||||
tbl = self._overviewTable()
|
|
||||||
self.web.stdHtml(self._overviewBody % dict(
|
|
||||||
title=_("Overview"),
|
|
||||||
table=tbl,
|
|
||||||
fcsub=_("Due over next two weeks"),
|
|
||||||
fcdata=fc,
|
|
||||||
opts=self._ovOpts(),
|
|
||||||
), css)
|
|
||||||
|
|
||||||
def _overviewTable(self):
|
|
||||||
counts = self._ovCounts()
|
|
||||||
def but(link, name):
|
|
||||||
return '<a class=but href="%s">%s</a>' % (link, name)
|
|
||||||
buf = "<table cellspacing=0 cellpadding=3 width=400>"
|
|
||||||
buf += "<tr><th></th><th align=right>%s</th>" % _("Due")
|
|
||||||
buf += "<th align=right>%s</th><th></th></tr>" % _("New")
|
|
||||||
line = "<tr><td><b>%s</b></td><td class=due>%s</td>"
|
|
||||||
line += "<td class=new>%s</td><td align=right>%s</td></tr>"
|
|
||||||
buf += line % (
|
|
||||||
"<a href=chgrp>%s</a>" % _("Selected Groups"),
|
|
||||||
counts[0], counts[1],
|
|
||||||
but("studysel", _("Study")) +
|
|
||||||
but("cramsel", _("Cram")))
|
|
||||||
buf += line % (
|
|
||||||
_("Whole Deck"),
|
|
||||||
counts[2], counts[3],
|
|
||||||
but("studyall", _("Study")) +
|
|
||||||
but("cramall", _("Cram")))
|
|
||||||
buf += "</table>"
|
|
||||||
return buf
|
|
||||||
|
|
||||||
def _ovCounts(self):
|
|
||||||
oldNew = self.mw.deck.qconf['newGroups']
|
|
||||||
oldRev = self.mw.deck.qconf['revGroups']
|
|
||||||
# we have the limited count already
|
|
||||||
selcnt = self.mw.deck.sched.selCounts()
|
|
||||||
allcnt = self.mw.deck.sched.allCounts()
|
|
||||||
return [
|
|
||||||
selcnt[1] + selcnt[2],
|
|
||||||
selcnt[0],
|
|
||||||
allcnt[1] + allcnt[2],
|
|
||||||
allcnt[0],
|
|
||||||
]
|
|
||||||
|
|
||||||
def _ovForecast(self):
|
|
||||||
fc = self.mw.deck.sched.dueForecast(14)
|
|
||||||
if not sum(fc):
|
|
||||||
return "''"
|
|
||||||
return simplejson.dumps(tuple(enumerate(fc)))
|
|
||||||
|
|
||||||
def _ovOpts(self):
|
|
||||||
if self.mw.deck.qconf['newCardOrder'] == NEW_CARDS_RANDOM:
|
|
||||||
ord = _("random")
|
|
||||||
else:
|
|
||||||
ord = _("order added")
|
|
||||||
buf = """
|
|
||||||
<table width=400>
|
|
||||||
<tr><td><b>%s</b></td><td align=center>%s</td><td align=right rowspan=2>%s</td></tr>
|
|
||||||
<tr><td><b>%s</b></td><td align=center>%s</td></tr>
|
|
||||||
</table>""" % (
|
|
||||||
_("New cards per day"), self.mw.deck.qconf['newPerDay'],
|
|
||||||
'<a href=opts class=but>%s</a>' % _("Study Options"),
|
|
||||||
_("New card order"), ord)
|
|
||||||
return buf
|
|
||||||
|
|
||||||
# State control
|
# State control
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _reset(self):
|
def _reset(self):
|
||||||
self._overview()
|
pass
|
||||||
|
|
||||||
def setState(self, state):
|
def setState(self, state):
|
||||||
"Change to STATE, and update the display."
|
"Change to STATE, and update the display."
|
||||||
|
@ -148,7 +43,7 @@ $(function () {
|
||||||
self.state = state
|
self.state = state
|
||||||
if self.state == "initial":
|
if self.state == "initial":
|
||||||
return
|
return
|
||||||
elif self.state == "noDeck":
|
elif self.state == "deckBrowser":
|
||||||
self.clearWindow()
|
self.clearWindow()
|
||||||
self.drawWelcomeMessage()
|
self.drawWelcomeMessage()
|
||||||
self.flush()
|
self.flush()
|
||||||
|
@ -157,7 +52,7 @@ $(function () {
|
||||||
|
|
||||||
def redisplay(self):
|
def redisplay(self):
|
||||||
"Idempotently display the current state (prompt for question, etc)"
|
"Idempotently display the current state (prompt for question, etc)"
|
||||||
if self.state == "noDeck" or self.state == "studyScreen":
|
if self.state == "deckBrowser" or self.state == "studyScreen":
|
||||||
return
|
return
|
||||||
self.buffer = ""
|
self.buffer = ""
|
||||||
self.haveTop = self.needFutureWarning()
|
self.haveTop = self.needFutureWarning()
|
||||||
|
|
|
@ -31,7 +31,7 @@ class StatusView(object):
|
||||||
self.statusbar = parent.mainWin.statusbar
|
self.statusbar = parent.mainWin.statusbar
|
||||||
self.shown = []
|
self.shown = []
|
||||||
self.hideBorders()
|
self.hideBorders()
|
||||||
self.setState("noDeck")
|
self.setState("deckBrowser")
|
||||||
self.timer = None
|
self.timer = None
|
||||||
self.timerFlashStart = 0
|
self.timerFlashStart = 0
|
||||||
self.thinkingTimer = QTimer(parent)
|
self.thinkingTimer = QTimer(parent)
|
||||||
|
@ -53,7 +53,7 @@ class StatusView(object):
|
||||||
self.state = state
|
self.state = state
|
||||||
if self.state == "initial":
|
if self.state == "initial":
|
||||||
self.showDeckStatus()
|
self.showDeckStatus()
|
||||||
elif self.state == "noDeck":
|
elif self.state == "deckBrowser":
|
||||||
self.hideDeckStatus()
|
self.hideDeckStatus()
|
||||||
elif self.state in ("showQuestion",
|
elif self.state in ("showQuestion",
|
||||||
"deckFinished",
|
"deckFinished",
|
||||||
|
|
Loading…
Reference in a new issue