start work on an overview; add flot to resources

This commit is contained in:
Damien Elmes 2011-03-21 16:49:06 +09:00
parent 81d29fedd5
commit c9c7b8c25b
6 changed files with 154 additions and 37 deletions

View file

@ -11,35 +11,6 @@ from anki.utils import fmtTimeSpan
from anki.hooks import addHook
import aqt
_css = """
body { background-color: #eee; }
#outer { margin-top: 1em; }
.sub { color: #555; }
hr { margin:5 0 5 0; border:0; height:1px; background-color:#ddd; }
a:hover { background-color: #aaa; }
a.deck { color: #000; text-decoration: none; font-size: 100%; }
.num { text-align: right; padding: 0 5 0 5; }
a.opts { font-size: 80%; padding: 3; background-color: #ccc;
border-radius: 2px; color: #000; }
td.opts { text-align: right; white-space: nowrap; }
td.menu { text-align: center; }
a { font-size: 80%; text-decoration: none; }
h1 { margin-bottom: 0.2em; }
"""
_body = """
<center>
<div id="outer">
<h1>%(title)s</h1>
%(tb)s
<p>
<table cellspacing=0 cellpadding=0 width=90%%>
%(rows)s
</table>
%(extra)s
</div>
"""
class DeckBrowser(object):
"Display a list of remembered decks."
@ -147,28 +118,50 @@ class DeckBrowser(object):
# HTML generation
##########################################################################
_css = """
.sub { color: #555; }
a.deck { color: #000; text-decoration: none; font-size: 100%; }
.num { text-align: right; padding: 0 5 0 5; }
td.opts { text-align: right; white-space: nowrap; }
td.menu { text-align: center; }
a { font-size: 80%; }
"""
_body = """
<center>
<h1>%(title)s</h1>
%(tb)s
<p>
<table cellspacing=0 cellpadding=0 width=90%%>
%(rows)s
</table>
%(extra)s
</center>
"""
def _renderPage(self):
if self._decks:
buf = ""
css = self.mw._sharedCSS + self._css
max=len(self._decks)-1
for c, deck in enumerate(self._decks):
buf += self._deckRow(c, max, deck)
self.web.stdHtml(_body%dict(
self.web.stdHtml(self._body%dict(
title=_("Decks"),
rows=buf,
tb=self._toolbar(),
extra="<p>%s<p>%s" % (
self._summary(),
_("Click a deck to open it, or type a number."))),
_css)
css)
else:
self.web.stdHtml(_body%dict(
self.web.stdHtml(self._body%dict(
title=_("Welcome!"),
rows="<tr><td align=center>%s</td></tr>"%_(
"Click <b>Download</b> to get started."),
extra="",
tb=self._toolbar()),
_css)
css)
def _deckRow(self, c, max, deck):
buf = "<tr>"
@ -212,7 +205,7 @@ class DeckBrowser(object):
# no counts
buf += "<td colspan=2></td>"
# options
buf += "<td class=opts><a class=opts href='opts:%d'>%s&#9660;</a></td>" % (
buf += "<td class=opts><a class=but href='opts:%d'>%s&#9660;</a></td>" % (
c, "Options")
buf += "</tr>"
if c != max:

View file

@ -81,6 +81,17 @@ class AnkiQt(QMainWindow):
self.setupEditor()
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
##########################################################################

View file

@ -2,10 +2,11 @@
# Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
import time, os, stat, shutil, difflib
import time, os, stat, shutil, difflib, simplejson
import unicodedata as ucd
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from anki.consts import NEW_CARDS_RANDOM
from anki.utils import fmtTimeSpan, stripHTML
from anki.hooks import addHook, runHook, runFilter
from anki.sound import playFromText
@ -30,11 +31,118 @@ class Reviewer(object):
self._setupToolbar()
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>
%(opts)s
</center>
<script id="source" language="javascript" type="text/javascript">
$(function () {
var d = %(fcdata)s;
$.plot($("#placeholder"), [
{ data: d, bars: { show: true, barWidth: 0.8 } }
], {
xaxis: { ticks: [[0.5, "Today"]] }
});
});
</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
self.web.stdHtml(self._overviewBody % dict(
title=_("Overview"),
table=self._overviewTable(),
fcsub=_("Due over next two weeks"),
fcdata=self._ovForecast(),
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']
if not oldNew and not oldRev:
# everything is enabled, no extra work to work to do
self.mw.deck.reset()
allcnt = self.mw.deck.sched.counts()
else:
# need to reset to find all cards
self.mw.deck.qconf['newGroups'] = []
self.mw.deck.qconf['revGroups'] = []
self.mw.deck.reset()
allcnt = self.mw.deck.sched.counts()
self.mw.deck.qconf['newGroups'] = oldNew
self.mw.deck.qconf['revGroups'] = oldRev
self.mw.deck.reset()
selcnt = self.mw.deck.sched.counts()
return [
selcnt[1] + selcnt[2],
selcnt[0],
allcnt[1] + allcnt[2],
allcnt[0],
]
def _ovForecast(self):
return simplejson.dumps(tuple(
enumerate(self.mw.deck.sched.dueForecast(14))))
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
##########################################################################
def _reset(self):
self.web.stdHtml("")
self._overview()
def setState(self, state):
"Change to STATE, and update the display."

View file

@ -66,7 +66,10 @@ class AnkiWebView(QWebView):
QWebView.setHtml(self, html)
def stdHtml(self, body, css="", loadCB=None):
self.setHtml("""
<html><head><style>%s</style><script src="qrc:/jquery.min.js"></script></head>
<html><head><style>%s</style>
<script src="qrc:/jquery.min.js"></script>
<script src="qrc:/jquery.flot.min.js"></script>
</head>
<body>%s</body></html>""" % (css, body), loadCB)
# ensure we're focused
self.setFocus()

View file

@ -95,5 +95,6 @@
<file>icons/view-pim-news.png</file>
<file>icons/view_text.png</file>
<file>jquery.min.js</file>
<file>jquery.flot.min.js</file>
</qresource>
</RCC>

1
designer/jquery.flot.min.js vendored Normal file

File diff suppressed because one or more lines are too long