merge deck stats and graphs together

This commit is contained in:
Damien Elmes 2011-03-30 21:12:46 +09:00
parent 0ab698154f
commit 7ab89d2637
4 changed files with 209 additions and 121 deletions

View file

@ -526,7 +526,7 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
tb.addAction(frm.actionEditLayout) tb.addAction(frm.actionEditLayout)
tb.addAction(frm.actionEditdeck) tb.addAction(frm.actionEditdeck)
tb.addAction(frm.actionOverview) tb.addAction(frm.actionOverview)
tb.addAction(frm.actionGraphs) tb.addAction(frm.actionStats)
tb.addAction(frm.actionMarkCard) tb.addAction(frm.actionMarkCard)
tb.addAction(frm.actionRepeatAudio) tb.addAction(frm.actionRepeatAudio)
tb.addAction(frm.actionClose) tb.addAction(frm.actionClose)
@ -651,11 +651,8 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors")
def onCardStats(self): def onCardStats(self):
self.cardStats.show() self.cardStats.show()
def onDeckStats(self): def onStats(self):
aqt.stats.deckStats(self) aqt.stats.DeckStats(self)
def onGraphs(self):
aqt.stats.graphs(self)
def onCardLayout(self): def onCardLayout(self):
aqt.clayout.CardLayout(self, 0, self.currentCard.fact, aqt.clayout.CardLayout(self, 0, self.currentCard.fact,
@ -740,8 +737,7 @@ Please choose a new deck name:"""))
"DeckProperties", "DeckProperties",
"Undo", "Undo",
"Export", "Export",
"Graphs", "Stats",
"Dstats",
"Cstats", "Cstats",
"StudyOptions", "StudyOptions",
"Overview", "Overview",
@ -765,9 +761,8 @@ Please choose a new deck name:"""))
self.connect(m.actionEditdeck, s, self.onEditDeck) self.connect(m.actionEditdeck, s, self.onEditDeck)
self.connect(m.actionEditCurrent, s, self.onEditCurrent) self.connect(m.actionEditCurrent, s, self.onEditCurrent)
self.connect(m.actionPreferences, s, self.onPrefs) 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.actionCstats, s, self.onCardStats)
self.connect(m.actionGraphs, s, self.onGraphs)
self.connect(m.actionEditLayout, s, self.onCardLayout) self.connect(m.actionEditLayout, s, self.onCardLayout)
self.connect(m.actionAbout, s, self.onAbout) self.connect(m.actionAbout, s, self.onAbout)
self.connect(m.actionImport, s, self.onImport) self.connect(m.actionImport, s, self.onImport)

View file

@ -8,6 +8,7 @@ import os, tempfile
from aqt.webview import AnkiWebView from aqt.webview import AnkiWebView
from aqt.utils import saveGeom, restoreGeom from aqt.utils import saveGeom, restoreGeom
from anki.hooks import addHook from anki.hooks import addHook
import aqt
# Card stats # Card stats
###################################################################### ######################################################################
@ -58,51 +59,44 @@ class CardStats(object):
<style>table { font-size: 12px; } h1 { font-size: 14px; }</style> <style>table { font-size: 12px; } h1 { font-size: 14px; }</style>
</head><body><center>%s</center></body></html>"""%txt) </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): def __init__(self, mw):
self.mw = mw
QDialog.__init__(self, mw) QDialog.__init__(self, mw)
restoreGeom(self, type) self.mw = mw
self.type = type self.name = "deckStats"
self.setWindowTitle(title) self.period = 0
self.setModal(True) self.sel = True
self.mw.progress.start() self.form = aqt.forms.stats.Ui_Dialog()
self.web = AnkiWebView(self) f = self.form
l = QVBoxLayout(self) f.setupUi(self)
l.setContentsMargins(0,0,0,0) restoreGeom(self, self.name)
l.addWidget(self.web) b = f.buttonBox.addButton(_("Save Image"),
self.css = css QDialogButtonBox.ActionRole)
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)
b.connect(b, SIGNAL("clicked()"), self.browser) b.connect(b, SIGNAL("clicked()"), self.browser)
b.setAutoDefault(False) b.setAutoDefault(False)
self.layout = QHBoxLayout() c = self.connect
self.layout.setContentsMargins(0,0,0,0) s = SIGNAL("clicked()")
self.layout.addWidget(self.box) c(f.groups, s, lambda: self.changeSel(True))
l.addLayout(self.layout) c(f.all, s, lambda: self.changeSel(False))
self.setLayout(l) c(f.month, s, lambda: self.changePeriod(0))
self.connect(self.box, SIGNAL("rejected()"), self, SLOT("reject()")) c(f.year, s, lambda: self.changePeriod(1))
self.mw.progress.finish() c(f.life, s, lambda: self.changePeriod(2))
self.refresh()
def run(self):
self.exec_() self.exec_()
def reject(self): def reject(self):
saveGeom(self, self.type) saveGeom(self, self.name)
QDialog.reject(self) QDialog.reject(self)
def browser(self): def browser(self):
# dump to a temporary file # dump to a temporary file
tmpdir = tempfile.mkdtemp(prefix="anki") tmpdir = tempfile.mkdtemp(prefix="anki")
path = os.path.join(tmpdir, "report.png") path = os.path.join(tmpdir, "report.png")
p = self.web.page() p = self.form.web.page()
oldsize = p.viewportSize() oldsize = p.viewportSize()
p.setViewportSize(p.mainFrame().contentsSize()) p.setViewportSize(p.mainFrame().contentsSize())
image = QImage(p.viewportSize(), QImage.Format_ARGB32) image = QImage(p.viewportSize(), QImage.Format_ARGB32)
@ -113,73 +107,17 @@ class PrintableReport(QDialog):
p.setViewportSize(oldsize) p.setViewportSize(oldsize)
QDesktopServices.openUrl(QUrl("file://" + path)) 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): def changePeriod(self, n):
self.period = n self.period = n
self.refresh() self.refresh()
def changeSel(self, sel):
self.sel = sel
self.refresh()
def refresh(self): def refresh(self):
self.mw.progress.start(immediate=True) self.mw.progress.start(immediate=True)
self.report = self.mw.deck.graphs().report(type=self.period) self.report = self.mw.deck.graphs().report(
self.web.stdHtml(self.report, css=self.css) type=self.period, selective=self.sel)
self.form.web.setHtml(self.report)
self.mw.progress.finish() 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()

View file

@ -113,8 +113,7 @@
<addaction name="actionLocalizeMedia"/> <addaction name="actionLocalizeMedia"/>
<addaction name="separator"/> <addaction name="separator"/>
</widget> </widget>
<addaction name="actionGraphs"/> <addaction name="actionStats"/>
<addaction name="actionDstats"/>
<addaction name="actionCstats"/> <addaction name="actionCstats"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionRepeatAudio"/> <addaction name="actionRepeatAudio"/>
@ -321,18 +320,6 @@
<enum>QAction::PreferencesRole</enum> <enum>QAction::PreferencesRole</enum>
</property> </property>
</action> </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>&amp;Deck Statistics</string>
</property>
<property name="shortcut">
<string>Shift+D</string>
</property>
</action>
<action name="actionAbout"> <action name="actionAbout">
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
@ -351,7 +338,7 @@
<normaloff>:/icons/package_games_card.png</normaloff>:/icons/package_games_card.png</iconset> <normaloff>:/icons/package_games_card.png</normaloff>:/icons/package_games_card.png</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Card Statistics</string> <string>&amp;Card Info</string>
</property> </property>
<property name="statusTip"> <property name="statusTip">
<string>Show statistics about the current card and last card</string> <string>Show statistics about the current card and last card</string>
@ -387,19 +374,19 @@
<string>Ctrl+I</string> <string>Ctrl+I</string>
</property> </property>
</action> </action>
<action name="actionGraphs"> <action name="actionStats">
<property name="icon"> <property name="icon">
<iconset resource="icons.qrc"> <iconset resource="icons.qrc">
<normaloff>:/icons/view-statistics.png</normaloff>:/icons/view-statistics.png</iconset> <normaloff>:/icons/view-statistics.png</normaloff>:/icons/view-statistics.png</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;Graphs...</string> <string>&amp;Statistics...</string>
</property> </property>
<property name="statusTip"> <property name="statusTip">
<string/> <string/>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Shift+G</string> <string>Shift+S</string>
</property> </property>
</action> </action>
<action name="actionExport"> <action name="actionExport">

168
designer/stats.ui Normal file
View 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>