mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 07:22:23 -04:00
support for saving stats to a pdf
This commit is contained in:
parent
e6adc3c195
commit
ed07a147f9
2 changed files with 37 additions and 40 deletions
|
@ -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:
|
||||||
|
|
33
aqt/stats.py
33
aqt/stats.py
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue