mirror of
https://github.com/ankitects/anki.git
synced 2025-11-10 14:47:12 -05:00
merge deck stats and graphs together
This commit is contained in:
parent
0ab698154f
commit
7ab89d2637
4 changed files with 209 additions and 121 deletions
15
aqt/main.py
15
aqt/main.py
|
|
@ -526,7 +526,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
|||
tb.addAction(frm.actionEditLayout)
|
||||
tb.addAction(frm.actionEditdeck)
|
||||
tb.addAction(frm.actionOverview)
|
||||
tb.addAction(frm.actionGraphs)
|
||||
tb.addAction(frm.actionStats)
|
||||
tb.addAction(frm.actionMarkCard)
|
||||
tb.addAction(frm.actionRepeatAudio)
|
||||
tb.addAction(frm.actionClose)
|
||||
|
|
@ -651,11 +651,8 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
|
|||
def onCardStats(self):
|
||||
self.cardStats.show()
|
||||
|
||||
def onDeckStats(self):
|
||||
aqt.stats.deckStats(self)
|
||||
|
||||
def onGraphs(self):
|
||||
aqt.stats.graphs(self)
|
||||
def onStats(self):
|
||||
aqt.stats.DeckStats(self)
|
||||
|
||||
def onCardLayout(self):
|
||||
aqt.clayout.CardLayout(self, 0, self.currentCard.fact,
|
||||
|
|
@ -740,8 +737,7 @@ Please choose a new deck name:"""))
|
|||
"DeckProperties",
|
||||
"Undo",
|
||||
"Export",
|
||||
"Graphs",
|
||||
"Dstats",
|
||||
"Stats",
|
||||
"Cstats",
|
||||
"StudyOptions",
|
||||
"Overview",
|
||||
|
|
@ -765,9 +761,8 @@ Please choose a new deck name:"""))
|
|||
self.connect(m.actionEditdeck, s, self.onEditDeck)
|
||||
self.connect(m.actionEditCurrent, s, self.onEditCurrent)
|
||||
self.connect(m.actionPreferences, s, self.onPrefs)
|
||||
self.connect(m.actionDstats, s, self.onDeckStats)
|
||||
self.connect(m.actionStats, s, self.onStats)
|
||||
self.connect(m.actionCstats, s, self.onCardStats)
|
||||
self.connect(m.actionGraphs, s, self.onGraphs)
|
||||
self.connect(m.actionEditLayout, s, self.onCardLayout)
|
||||
self.connect(m.actionAbout, s, self.onAbout)
|
||||
self.connect(m.actionImport, s, self.onImport)
|
||||
|
|
|
|||
124
aqt/stats.py
124
aqt/stats.py
|
|
@ -8,6 +8,7 @@ import os, tempfile
|
|||
from aqt.webview import AnkiWebView
|
||||
from aqt.utils import saveGeom, restoreGeom
|
||||
from anki.hooks import addHook
|
||||
import aqt
|
||||
|
||||
# Card stats
|
||||
######################################################################
|
||||
|
|
@ -58,51 +59,44 @@ class CardStats(object):
|
|||
<style>table { font-size: 12px; } h1 { font-size: 14px; }</style>
|
||||
</head><body><center>%s</center></body></html>"""%txt)
|
||||
|
||||
# Modal dialog that supports dumping to browser (for printing, etc)
|
||||
# Deck Stats
|
||||
######################################################################
|
||||
|
||||
class PrintableReport(QDialog):
|
||||
class DeckStats(QDialog):
|
||||
|
||||
def __init__(self, mw, type, title, func, css):
|
||||
self.mw = mw
|
||||
def __init__(self, mw):
|
||||
QDialog.__init__(self, mw)
|
||||
restoreGeom(self, type)
|
||||
self.type = type
|
||||
self.setWindowTitle(title)
|
||||
self.setModal(True)
|
||||
self.mw.progress.start()
|
||||
self.web = AnkiWebView(self)
|
||||
l = QVBoxLayout(self)
|
||||
l.setContentsMargins(0,0,0,0)
|
||||
l.addWidget(self.web)
|
||||
self.css = css
|
||||
if func:
|
||||
self.report = func()
|
||||
self.web.stdHtml(self.report, css=css)
|
||||
self.box = QDialogButtonBox(QDialogButtonBox.Close)
|
||||
b = self.box.addButton(_("Save Image"), QDialogButtonBox.ActionRole)
|
||||
self.mw = mw
|
||||
self.name = "deckStats"
|
||||
self.period = 0
|
||||
self.sel = True
|
||||
self.form = aqt.forms.stats.Ui_Dialog()
|
||||
f = self.form
|
||||
f.setupUi(self)
|
||||
restoreGeom(self, self.name)
|
||||
b = f.buttonBox.addButton(_("Save Image"),
|
||||
QDialogButtonBox.ActionRole)
|
||||
b.connect(b, SIGNAL("clicked()"), self.browser)
|
||||
b.setAutoDefault(False)
|
||||
self.layout = QHBoxLayout()
|
||||
self.layout.setContentsMargins(0,0,0,0)
|
||||
self.layout.addWidget(self.box)
|
||||
l.addLayout(self.layout)
|
||||
self.setLayout(l)
|
||||
self.connect(self.box, SIGNAL("rejected()"), self, SLOT("reject()"))
|
||||
self.mw.progress.finish()
|
||||
|
||||
def run(self):
|
||||
c = self.connect
|
||||
s = SIGNAL("clicked()")
|
||||
c(f.groups, s, lambda: self.changeSel(True))
|
||||
c(f.all, s, lambda: self.changeSel(False))
|
||||
c(f.month, s, lambda: self.changePeriod(0))
|
||||
c(f.year, s, lambda: self.changePeriod(1))
|
||||
c(f.life, s, lambda: self.changePeriod(2))
|
||||
self.refresh()
|
||||
self.exec_()
|
||||
|
||||
def reject(self):
|
||||
saveGeom(self, self.type)
|
||||
saveGeom(self, self.name)
|
||||
QDialog.reject(self)
|
||||
|
||||
def browser(self):
|
||||
# dump to a temporary file
|
||||
tmpdir = tempfile.mkdtemp(prefix="anki")
|
||||
path = os.path.join(tmpdir, "report.png")
|
||||
p = self.web.page()
|
||||
p = self.form.web.page()
|
||||
oldsize = p.viewportSize()
|
||||
p.setViewportSize(p.mainFrame().contentsSize())
|
||||
image = QImage(p.viewportSize(), QImage.Format_ARGB32)
|
||||
|
|
@ -113,73 +107,17 @@ class PrintableReport(QDialog):
|
|||
p.setViewportSize(oldsize)
|
||||
QDesktopServices.openUrl(QUrl("file://" + path))
|
||||
|
||||
# Deck stats
|
||||
######################################################################
|
||||
|
||||
def deckStats(mw):
|
||||
css=mw.sharedCSS+"""
|
||||
body { margin: 2em; font-family: arial; }
|
||||
h1 { font-size: 18px; border-bottom: 1px solid #000; margin-top: 1em;
|
||||
clear: both; margin-bottom: 0.5em; }
|
||||
.info {float:right; padding: 10px; max-width: 300px; border-radius: 5px;
|
||||
background: #ddd; font-size: 14px; }
|
||||
"""
|
||||
return PrintableReport(
|
||||
mw,
|
||||
"deckstats",
|
||||
_("Deck Statistics"),
|
||||
mw.deck.deckStats,
|
||||
css).run()
|
||||
|
||||
# Graphs
|
||||
######################################################################
|
||||
|
||||
class Graphs(PrintableReport):
|
||||
|
||||
def __init__(self, *args):
|
||||
self.period = 0
|
||||
self.periods = [
|
||||
_("1 month"),
|
||||
_("1 year"),
|
||||
_("deck life")]
|
||||
PrintableReport.__init__(self, *args)
|
||||
grp = QGroupBox()
|
||||
l = QHBoxLayout()
|
||||
l.setContentsMargins(6,6,6,6)
|
||||
chk = False
|
||||
for c, p in enumerate(self.periods):
|
||||
b = QRadioButton(p)
|
||||
if not chk:
|
||||
b.setChecked(True)
|
||||
chk = True
|
||||
b.connect(b, SIGNAL("clicked()"), lambda n=c: self.changePeriod(n))
|
||||
l.addWidget(b)
|
||||
grp.setLayout(l)
|
||||
self.layout.insertWidget(0, grp)
|
||||
self.layout.insertStretch(0, 10)
|
||||
self.refresh()
|
||||
|
||||
def changePeriod(self, n):
|
||||
self.period = n
|
||||
self.refresh()
|
||||
|
||||
def changeSel(self, sel):
|
||||
self.sel = sel
|
||||
self.refresh()
|
||||
|
||||
def refresh(self):
|
||||
self.mw.progress.start(immediate=True)
|
||||
self.report = self.mw.deck.graphs().report(type=self.period)
|
||||
self.web.stdHtml(self.report, css=self.css)
|
||||
self.report = self.mw.deck.graphs().report(
|
||||
type=self.period, selective=self.sel)
|
||||
self.form.web.setHtml(self.report)
|
||||
self.mw.progress.finish()
|
||||
|
||||
def graphs(mw):
|
||||
css=mw.sharedCSS+"""
|
||||
body { margin: 2em; font-family: arial; background: #eee; }
|
||||
h1 { font-size: 18px; border-bottom: 1px solid #000; margin-top: 1em;
|
||||
clear: both; margin-bottom: 0.5em; }
|
||||
.info {float:right; padding: 10px; max-width: 300px; border-radius: 5px;
|
||||
background: #ddd; font-size: 14px; }
|
||||
"""
|
||||
return Graphs(
|
||||
mw,
|
||||
"graphs",
|
||||
_("Graphs"),
|
||||
None,
|
||||
css).run()
|
||||
|
|
|
|||
|
|
@ -113,8 +113,7 @@
|
|||
<addaction name="actionLocalizeMedia"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<addaction name="actionGraphs"/>
|
||||
<addaction name="actionDstats"/>
|
||||
<addaction name="actionStats"/>
|
||||
<addaction name="actionCstats"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRepeatAudio"/>
|
||||
|
|
@ -321,18 +320,6 @@
|
|||
<enum>QAction::PreferencesRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDstats">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/spreadsheet.png</normaloff>:/icons/spreadsheet.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Deck Statistics</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Shift+D</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
|
|
@ -351,7 +338,7 @@
|
|||
<normaloff>:/icons/package_games_card.png</normaloff>:/icons/package_games_card.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Card Statistics</string>
|
||||
<string>&Card Info</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string>Show statistics about the current card and last card</string>
|
||||
|
|
@ -387,19 +374,19 @@
|
|||
<string>Ctrl+I</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGraphs">
|
||||
<action name="actionStats">
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/view-statistics.png</normaloff>:/icons/view-statistics.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Graphs...</string>
|
||||
<string>&Statistics...</string>
|
||||
</property>
|
||||
<property name="statusTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Shift+G</string>
|
||||
<string>Shift+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport">
|
||||
|
|
|
|||
168
designer/stats.ui
Normal file
168
designer/stats.ui
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>607</width>
|
||||
<height>556</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Statistics</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWebView" name="web">
|
||||
<property name="url">
|
||||
<url>
|
||||
<string>about:blank</string>
|
||||
</url>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="groups">
|
||||
<property name="text">
|
||||
<string>groups</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="all">
|
||||
<property name="text">
|
||||
<string>all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="month">
|
||||
<property name="text">
|
||||
<string>1 month</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="year">
|
||||
<property name="text">
|
||||
<string>1 year</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="life">
|
||||
<property name="text">
|
||||
<string>deck life</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QWebView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>QtWebKit/QWebView</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
Loading…
Reference in a new issue