support for saving stats to a pdf

This commit is contained in:
Damien Elmes 2017-01-13 17:36:26 +10:00
parent e6adc3c195
commit ed07a147f9
2 changed files with 37 additions and 40 deletions

View file

@ -113,23 +113,29 @@ class CollectionStats(object):
self.type = type self.type = type
from .statsbg import bg from .statsbg import bg
txt = self.css % bg txt = self.css % bg
txt += self.todayStats() txt += self._section(self.todayStats())
txt += self.dueGraph() txt += self._section(self.dueGraph())
txt += self.repsGraph() txt += self.repsGraphs()
txt += self.introductionGraph() txt += self._section(self.introductionGraph())
txt += self.ivlGraph() txt += self._section(self.ivlGraph())
txt += self.hourGraph() txt += self._section(self.hourGraph())
txt += self.easeGraph() txt += self._section(self.easeGraph())
txt += self.cardGraph() txt += self._section(self.cardGraph())
txt += self.footer() txt += self._section(self.footer())
return "<script>%s\n</script><center>%s</center>" % ( return "<script>%s\n</script><center>%s</center>" % (
anki.js.jquery+anki.js.plot, txt) anki.js.jquery+anki.js.plot, txt)
def _section(self, txt):
return "<div class=section>%s</div>" % txt
css = """ css = """
<style> <style>
h1 { margin-bottom: 0; margin-top: 1em; } h1 { margin-bottom: 0; margin-top: 1em; }
.pielabel { text-align:center; padding:0px; color:white; } .pielabel { text-align:center; padding:0px; color:white; }
body {background-image: url(data:image/png;base64,%s); } body {background-image: url(data:image/png;base64,%s); }
@media print {
.section { page-break-inside: avoid; padding-top: 5mm; }
}
</style> </style>
""" """
@ -297,19 +303,19 @@ group by day order by day""" % (self._limit(), lim),
return txt return txt
def repsGraph(self): def repsGraphs(self):
if self.type == 0: if self.type == 0:
days = 30; chunk = 1 days = 30; chunk = 1
elif self.type == 1: elif self.type == 1:
days = 52; chunk = 7 days = 52; chunk = 7
else: else:
days = None; chunk = 30 days = None; chunk = 30
return self._repsGraph(self._done(days, chunk), return self._repsGraphs(self._done(days, chunk),
days, days,
_("Review Count"), _("Review Count"),
_("Review Time")) _("Review Time"))
def _repsGraph(self, data, days, reptitle, timetitle): def _repsGraphs(self, data, days, reptitle, timetitle):
if not data: if not data:
return "" return ""
d = data d = data
@ -328,13 +334,13 @@ group by day order by day""" % (self._limit(), lim),
(4, colRelearn, _("Relearn")), (4, colRelearn, _("Relearn")),
(1, colLearn, _("Learn")), (1, colLearn, _("Learn")),
(5, colCram, _("Cram")))) (5, colCram, _("Cram"))))
txt = self._title( txt1 = self._title(
reptitle, _("The number of questions you have answered.")) reptitle, _("The number of questions you have answered."))
txt += plot("reps", repdata, ylabel=_("Answers"), ylabel2=_( txt1 += plot("reps", repdata, ylabel=_("Answers"), ylabel2=_(
"Cumulative Answers")) "Cumulative Answers"))
(daysStud, fstDay) = self._daysStudied() (daysStud, fstDay) = self._daysStudied()
rep, tot = self._ansInfo(repsum, daysStud, fstDay, _("reviews")) rep, tot = self._ansInfo(repsum, daysStud, fstDay, _("reviews"))
txt += rep txt1 += rep
# time # time
(timdata, timsum) = self._splitRepData(d, ( (timdata, timsum) = self._splitRepData(d, (
(8, colMature, _("Mature")), (8, colMature, _("Mature")),
@ -348,12 +354,12 @@ group by day order by day""" % (self._limit(), lim),
else: else:
t = _("Hours") t = _("Hours")
convHours = True convHours = True
txt += self._title(timetitle, _("The time taken to answer the questions.")) txt2 = self._title(timetitle, _("The time taken to answer the questions."))
txt += plot("time", timdata, ylabel=t, ylabel2=_("Cumulative %s") % t) txt2 += plot("time", timdata, ylabel=t, ylabel2=_("Cumulative %s") % t)
rep, tot2 = self._ansInfo( rep, tot2 = self._ansInfo(
timsum, daysStud, fstDay, _("minutes"), convHours, total=tot) timsum, daysStud, fstDay, _("minutes"), convHours, total=tot)
txt += rep txt2 += rep
return txt return self._section(txt1) + self._section(txt2)
def _ansInfo(self, totd, studied, first, unit, convHours=False, total=None): def _ansInfo(self, totd, studied, first, unit, convHours=False, total=None):
if not totd: if not totd:

View file

@ -4,7 +4,8 @@
from aqt.qt import * from aqt.qt import *
import os, time import os, time
from aqt.utils import saveGeom, restoreGeom, maybeHideClose, showInfo, addCloseShortcut from aqt.utils import saveGeom, restoreGeom, maybeHideClose, addCloseShortcut, \
tooltip
import aqt import aqt
# Deck Stats # Deck Stats
@ -25,9 +26,9 @@ class DeckStats(QDialog):
f = self.form f = self.form
f.setupUi(self) f.setupUi(self)
restoreGeom(self, self.name) restoreGeom(self, self.name)
b = f.buttonBox.addButton(_("Save Image"), b = f.buttonBox.addButton(_("Save PDF"),
QDialogButtonBox.ActionRole) QDialogButtonBox.ActionRole)
b.clicked.connect(self.browser) b.clicked.connect(self.saveImage)
b.setAutoDefault(False) b.setAutoDefault(False)
f.groups.clicked.connect(lambda: self.changeScope("deck")) f.groups.clicked.connect(lambda: self.changeScope("deck"))
f.groups.setShortcut("g") f.groups.setShortcut("g")
@ -39,14 +40,13 @@ class DeckStats(QDialog):
addCloseShortcut(self) addCloseShortcut(self)
self.refresh() self.refresh()
self.show() self.show()
print("fixme: save image support in deck stats")
def reject(self): def reject(self):
saveGeom(self, self.name) saveGeom(self, self.name)
QDialog.reject(self) QDialog.reject(self)
def browser(self): def _imagePath(self):
name = time.strftime("-%Y-%m-%d@%H-%M-%S.png", name = time.strftime("-%Y-%m-%d@%H-%M-%S.pdf",
time.localtime(time.time())) time.localtime(time.time()))
name = "anki-"+_("stats")+name name = "anki-"+_("stats")+name
desktopPath = QStandardPaths.writableLocation( desktopPath = QStandardPaths.writableLocation(
@ -54,21 +54,12 @@ class DeckStats(QDialog):
if not os.path.exists(desktopPath): if not os.path.exists(desktopPath):
os.mkdir(desktopPath) os.mkdir(desktopPath)
path = os.path.join(desktopPath, name) path = os.path.join(desktopPath, name)
p = self.form.web.page() return path
oldsize = p.viewportSize()
p.setViewportSize(p.mainFrame().contentsSize()) def saveImage(self):
image = QImage(p.viewportSize(), QImage.Format_ARGB32) path = self._imagePath()
painter = QPainter(image) self.form.web.page().printToPdf(path)
p.mainFrame().render(painter) tooltip(_("A PDF file was saved to your desktop."))
painter.end()
isOK = image.save(path, "png")
if isOK:
showInfo(_("An image was saved to your desktop."))
else:
showInfo(_("""\
Anki could not save the image. Please check that you have permission to write \
to your desktop."""))
p.setViewportSize(oldsize)
def changePeriod(self, n): def changePeriod(self, n):
self.period = n self.period = n