From 8fd29bed1c6d8945c5bad91f2372ca7cdf64a16f Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Tue, 13 Mar 2012 19:02:39 +0900 Subject: [PATCH] cram creation & config --- aqt/deckbrowser.py | 3 + aqt/dyndeckconf.py | 91 +++++++++++++++++++++ aqt/main.py | 26 +++++- aqt/overview.py | 5 -- designer/dyndconf.ui | 190 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 308 insertions(+), 7 deletions(-) create mode 100644 aqt/dyndeckconf.py create mode 100644 designer/dyndconf.ui diff --git a/aqt/deckbrowser.py b/aqt/deckbrowser.py index 67233c29e..7213f11ed 100644 --- a/aqt/deckbrowser.py +++ b/aqt/deckbrowser.py @@ -38,6 +38,8 @@ class DeckBrowser(object): self._onShared() elif cmd == "import": self.mw.onImport() + elif cmd == "cram": + self.mw.onCram() elif cmd == "drag": draggedDeckDid, ontoDeckDid = arg.split(',') self._dragDeckOnto(draggedDeckDid, ontoDeckDid) @@ -220,6 +222,7 @@ Are you sure you wish to delete all of the cards in %s?""")%deck['name']): links = [ ["shared", _("Get Shared")], ["import", _("Import File")], + ["cram", _("Cram")], ] buf = "" for b in links: diff --git a/aqt/dyndeckconf.py b/aqt/dyndeckconf.py new file mode 100644 index 000000000..45701178e --- /dev/null +++ b/aqt/dyndeckconf.py @@ -0,0 +1,91 @@ +# Copyright: Damien Elmes +# -*- coding: utf-8 -*- +# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +from aqt.qt import * +import aqt, simplejson +from anki.utils import ids2str +from aqt.utils import showInfo, showWarning, openHelp, getOnlyText +from operator import itemgetter + +class DeckConf(QDialog): + def __init__(self, mw): + QDialog.__init__(self, mw) + self.mw = mw + self.deck = self.mw.col.decks.current() + self.form = aqt.forms.dyndconf.Ui_Dialog() + self.form.setupUi(self) + self.mw.checkpoint(_("Options")) + self.setWindowModality(Qt.WindowModal) + self.connect(self.form.buttonBox, + SIGNAL("helpRequested()"), + lambda: openHelp("deckoptions")) + self.setWindowTitle(_("Options for %s") % self.deck['name']) + self.setupCombos() + self.loadConf() + self.exec_() + + def setupCombos(self): + import anki.consts as cs + f = self.form + f.order.addItems(cs.dynOrderLabels().values()) + + def loadConf(self): + f = self.form + d = self.deck + f.search.setText(d['search']) + f.steps.setText(self.listToUser(d['delays'])) + f.order.setCurrentIndex(d['order']) + f.limit.setValue(d['limit']) + f.fmult.setValue(d['fmult']*100) + + def saveConf(self): + f = self.form + d = self.deck + steps = self.userToList(f.steps) + if not steps: + return + d['steps'] = steps + d['search'] = f.search.text() + d['order'] = f.order.currentIndex() + d['limit'] = f.limit.value() + d['fmult'] = f.fmult.value() / 100.0 + self.mw.col.decks.save(d) + return True + + def reject(self): + self.accept() + + def accept(self): + if not self.saveConf(): + return + self.mw.col.sched.rebuildDyn() + self.mw.reset() + QDialog.accept(self) + + # Step load/save - fixme: share with std options screen + ######################################################## + + def listToUser(self, l): + return " ".join([str(x) for x in l]) + + def userToList(self, w, minSize=1): + items = unicode(w.text()).split(" ") + ret = [] + for i in items: + if not i: + continue + try: + i = float(i) + assert i > 0 + if i == int(i): + i = int(i) + ret.append(i) + except: + # invalid, don't update + showWarning(_("Steps must be numbers.")) + return + if len(ret) < minSize: + showWarning(_("At least one step is required.")) + return + return ret diff --git a/aqt/main.py b/aqt/main.py index 5913ec551..deca6809e 100755 --- a/aqt/main.py +++ b/aqt/main.py @@ -672,8 +672,12 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors") self.cardStats = aqt.stats.CardStats(self) def onDeckConf(self): - import aqt.deckconf - aqt.deckconf.DeckConf(self) + if self.col.decks.current()['dyn']: + import aqt.dyndeckconf + aqt.dyndeckconf.DeckConf(self) + else: + import aqt.deckconf + aqt.deckconf.DeckConf(self) def onOverview(self): self.col.reset() @@ -710,6 +714,24 @@ Debug info:\n%s""") % traceback.format_exc(), help="DeckErrors") import aqt.exporting aqt.exporting.ExportDialog(self) + # Cramming + ########################################################################## + + def onCram(self): + n = 1 + decks = self.col.decks.allNames() + while _("Cram %d") % n in decks: + n += 1 + name = _("Cram %d") % n + name = getOnlyText(_("Please name your cram deck."), default=name) + if not name: + return + if name in decks: + showWarning(_("The provided name was already in use.")) + return + did = self.col.decks.newDyn(name) + self.onDeckConf() + # Language handling ########################################################################## diff --git a/aqt/overview.py b/aqt/overview.py index 9f56eb9a4..40df6b992 100644 --- a/aqt/overview.py +++ b/aqt/overview.py @@ -39,10 +39,6 @@ class Overview(object): self.mw.moveToState("review") elif url == "anki": print "anki menu" - elif url == "cram": - return showInfo("not yet implemented") - #self.mw.col.cramGroups() - #self.mw.moveToState("review") elif url == "opts": self.mw.onDeckConf() elif url == "decks": @@ -144,7 +140,6 @@ text-align: left; def _renderBottom(self): links = [ ["opts", _("Options")], - ["cram", _("Cram")], ] buf = "" for b in links: diff --git a/designer/dyndconf.ui b/designer/dyndconf.ui new file mode 100644 index 000000000..10629232b --- /dev/null +++ b/designer/dyndconf.ui @@ -0,0 +1,190 @@ + + + Dialog + + + + 0 + 0 + 397 + 293 + + + + Dialog + + + + + + + + 1 + + + 999 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Search for: + + + + + + + Learning steps: + + + + + + + Card limit: + + + + + + + 100 + + + + + + + Display order: + + + + + + + % + + + + + + + Example: deck:french tag:hard + + + + + + + Interval on fail: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Help|QDialogButtonBox::Ok + + + + + + + search + steps + order + limit + fmult + buttonBox + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +