mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
227 lines
7.5 KiB
Python
227 lines
7.5 KiB
Python
# Copyright: Damien Elmes <anki@ichi2.net>
|
|
# -*- 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.dconf.Ui_Dialog()
|
|
self.form.setupUi(self)
|
|
self.mw.checkpoint(_("Options"))
|
|
self.setupConfs()
|
|
self.connect(self.form.buttonBox,
|
|
SIGNAL("helpRequested()"),
|
|
lambda: openHelp("StudyOptions"))
|
|
self.connect(self.form.confOpts, SIGNAL("clicked()"), self.confOpts)
|
|
self.form.confOpts.setText(u"▾")
|
|
self.connect(self.form.buttonBox.button(QDialogButtonBox.RestoreDefaults),
|
|
SIGNAL("clicked()"),
|
|
self.onRestore)
|
|
self.setupCombos()
|
|
self.setWindowTitle(_("Options for %s") % self.deck['name'])
|
|
self.exec_()
|
|
|
|
def setupCombos(self):
|
|
import anki.consts as cs
|
|
f = self.form
|
|
f.newOrder.addItems(cs.newCardOrderLabels().values())
|
|
f.revOrder.addItems(cs.revCardOrderLabels().values())
|
|
self.connect(f.newOrder, SIGNAL("currentIndexChanged(int)"),
|
|
self.onNewOrderChanged)
|
|
|
|
# Conf list
|
|
######################################################################
|
|
|
|
def setupConfs(self):
|
|
self.connect(self.form.dconf, SIGNAL("currentIndexChanged(int)"),
|
|
self.onConfChange)
|
|
self.conf = None
|
|
self.loadConfs()
|
|
|
|
def loadConfs(self):
|
|
current = self.deck['conf']
|
|
self.confList = self.mw.col.decks.allConf()
|
|
self.confList.sort(key=itemgetter('name'))
|
|
startOn = None
|
|
self.ignoreConfChange = True
|
|
self.form.dconf.clear()
|
|
for idx, conf in enumerate(self.confList):
|
|
self.form.dconf.addItem(conf['name'])
|
|
if conf['id'] == current:
|
|
startOn = idx
|
|
self.ignoreConfChange = False
|
|
self.form.dconf.setCurrentIndex(startOn)
|
|
self.onConfChange(startOn)
|
|
|
|
def confOpts(self):
|
|
m = QMenu(self.mw)
|
|
a = m.addAction(_("Add"))
|
|
a.connect(a, SIGNAL("triggered()"), self.addGroup)
|
|
a = m.addAction(_("Delete"))
|
|
a.connect(a, SIGNAL("triggered()"), self.remGroup)
|
|
a = m.addAction(_("Rename"))
|
|
a.connect(a, SIGNAL("triggered()"), self.renameGroup)
|
|
m.exec_(QCursor.pos())
|
|
|
|
def onConfChange(self, idx):
|
|
if self.ignoreConfChange:
|
|
return
|
|
if self.conf:
|
|
self.saveConf()
|
|
conf = self.confList[idx]
|
|
self.deck['conf'] = conf['id']
|
|
self.loadConf()
|
|
|
|
def addGroup(self):
|
|
name = getOnlyText(_("New options group name:"))
|
|
if not name:
|
|
return
|
|
# first, save currently entered data to current conf
|
|
self.saveConf()
|
|
# then clone the conf
|
|
id = self.mw.col.decks.confId(name, cloneFrom=self.conf)
|
|
# set the deck to the new conf
|
|
self.deck['conf'] = id
|
|
# then reload the conf list
|
|
self.loadConfs()
|
|
|
|
def remGroup(self):
|
|
if self.conf['id'] == 1:
|
|
showInfo(_("The default configuration can't be removed."), self)
|
|
else:
|
|
self.mw.col.decks.remConf(self.conf['id'])
|
|
self.deck['conf'] = 1
|
|
self.loadConfs()
|
|
|
|
def renameGroup(self):
|
|
name = getOnlyText(_("New name:"))
|
|
if not name:
|
|
return
|
|
self.conf['name'] = name
|
|
self.loadConfs()
|
|
|
|
# Loading
|
|
##################################################
|
|
|
|
def listToUser(self, l):
|
|
return " ".join([str(x) for x in l])
|
|
|
|
def loadConf(self):
|
|
self.conf = self.mw.col.decks.conf(self.deck['id'])
|
|
# new
|
|
c = self.conf['new']
|
|
f = self.form
|
|
f.lrnSteps.setText(self.listToUser(c['delays']))
|
|
f.lrnGradInt.setValue(c['ints'][0])
|
|
f.lrnEasyInt.setValue(c['ints'][1])
|
|
f.lrnFactor.setValue(c['initialFactor']/10.0)
|
|
f.newOrder.setCurrentIndex(c['order'])
|
|
f.newPerDay.setValue(c['perDay'])
|
|
f.separate.setChecked(c['separate'])
|
|
# rev
|
|
c = self.conf['rev']
|
|
f.revPerDay.setValue(c['perDay'])
|
|
f.revOrder.setCurrentIndex(c['order'])
|
|
f.revSpace.setValue(c['fuzz']*100)
|
|
f.revMinSpace.setValue(c['minSpace'])
|
|
f.easyBonus.setValue(c['ease4']*100)
|
|
f.fi1.setValue(c['fi'][0])
|
|
f.fi2.setValue(c['fi'][1])
|
|
# lapse
|
|
c = self.conf['lapse']
|
|
f.lapSteps.setText(self.listToUser(c['delays']))
|
|
f.lapMult.setValue(c['mult']*100)
|
|
f.lapMinInt.setValue(c['minInt'])
|
|
f.leechThreshold.setValue(c['leechFails'])
|
|
f.leechAction.setCurrentIndex(c['leechAction'])
|
|
# general
|
|
c = self.conf
|
|
f.maxTaken.setValue(c['maxTaken'])
|
|
f.autoplaySounds.setChecked(c['autoplay'])
|
|
|
|
def onRestore(self):
|
|
self.mw.col.decks.restoreToDefault(self.conf)
|
|
self.loadConf()
|
|
f = self.form
|
|
f.dayOffset.setValue(4)
|
|
f.lrnCutoff.setValue(20)
|
|
f.timeLimit.setValue(0)
|
|
|
|
# New order
|
|
##################################################
|
|
|
|
def onNewOrderChanged(self, new):
|
|
old = self.conf['new']['order']
|
|
if old == new:
|
|
return
|
|
self.conf['new']['order'] = new
|
|
self.mw.progress.start()
|
|
self.mw.col.sched.resortConf(self.conf)
|
|
self.mw.progress.finish()
|
|
|
|
# Saving
|
|
##################################################
|
|
|
|
def updateList(self, conf, key, w):
|
|
items = unicode(w.text()).split(" ")
|
|
ret = []
|
|
for i in items:
|
|
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
|
|
conf[key] = ret
|
|
|
|
def saveConf(self):
|
|
# new
|
|
c = self.conf['new']
|
|
f = self.form
|
|
self.updateList(c, 'delays', f.lrnSteps)
|
|
c['ints'][0] = f.lrnGradInt.value()
|
|
c['ints'][1] = f.lrnEasyInt.value()
|
|
c['initialFactor'] = f.lrnFactor.value()*10
|
|
c['order'] = f.newOrder.currentIndex()
|
|
c['perDay'] = f.newPerDay.value()
|
|
c['separate'] = f.separate.isChecked()
|
|
# rev
|
|
c = self.conf['rev']
|
|
c['perDay'] = f.revPerDay.value()
|
|
c['fuzz'] = f.revSpace.value()/100.0
|
|
c['minSpace'] = f.revMinSpace.value()
|
|
c['ease4'] = f.easyBonus.value()/100.0
|
|
c['order'] = f.revOrder.currentIndex()
|
|
c['fi'] = [f.fi1.value(), f.fi2.value()]
|
|
# lapse
|
|
c = self.conf['lapse']
|
|
self.updateList(c, 'delays', f.lapSteps)
|
|
c['mult'] = f.lapMult.value()/100.0
|
|
c['minInt'] = f.lapMinInt.value()
|
|
c['leechFails'] = f.leechThreshold.value()
|
|
c['leechAction'] = f.leechAction.currentIndex()
|
|
# general
|
|
c = self.conf
|
|
c['maxTaken'] = f.maxTaken.value()
|
|
c['autoplay'] = f.autoplaySounds.isChecked()
|
|
self.mw.col.decks.save(self.conf)
|
|
|
|
def reject(self):
|
|
self.accept()
|
|
|
|
def accept(self):
|
|
self.saveConf()
|
|
self.mw.reset()
|
|
QDialog.accept(self)
|