mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
Merge branch 'master' of https://github.com/dae/anki
This commit is contained in:
commit
367a961bba
12 changed files with 162 additions and 51 deletions
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
import pprint
|
||||
|
||||
import time
|
||||
from anki.utils import intTime, timestampID, joinFields
|
||||
|
@ -106,6 +107,7 @@ insert or replace into cards values
|
|||
self.odid,
|
||||
self.flags,
|
||||
self.data)
|
||||
self.col.log(self)
|
||||
|
||||
def flushSched(self):
|
||||
self.mod = intTime()
|
||||
|
@ -121,6 +123,7 @@ lapses=?, left=?, odue=?, odid=?, did=? where id = ?""",
|
|||
self.mod, self.usn, self.type, self.queue, self.due, self.ivl,
|
||||
self.factor, self.reps, self.lapses,
|
||||
self.left, self.odue, self.odid, self.did, self.id)
|
||||
self.col.log(self)
|
||||
|
||||
def q(self, reload=False, browser=False):
|
||||
return self.css() + self._getQA(reload, browser)['q']
|
||||
|
@ -180,3 +183,12 @@ lapses=?, left=?, odue=?, odid=?, did=? where id = ?""",
|
|||
self.model(), joinFields(self.note().fields))
|
||||
if self.ord not in ords:
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
d = dict(self.__dict__)
|
||||
# remove non-useful elements
|
||||
del d['_note']
|
||||
del d['_qa']
|
||||
del d['col']
|
||||
del d['timerStarted']
|
||||
return pprint.pformat(d, width=300)
|
||||
|
|
|
@ -51,6 +51,7 @@ class _Collection(object):
|
|||
def __init__(self, db, server=False):
|
||||
self.db = db
|
||||
self.path = db._path
|
||||
self.log(self.path, anki.version)
|
||||
self.server = server
|
||||
self._lastSave = time.time()
|
||||
self.clearUndo()
|
||||
|
@ -204,8 +205,11 @@ crt=?, mod=?, scm=?, dty=?, usn=?, ls=?, conf=?""",
|
|||
# Object creation helpers
|
||||
##########################################################################
|
||||
|
||||
def getCard(self, id):
|
||||
return anki.cards.Card(self, id)
|
||||
def getCard(self, id, log=True):
|
||||
c = anki.cards.Card(self, id)
|
||||
if log:
|
||||
self.log(c, stack=1)
|
||||
return c
|
||||
|
||||
def getNote(self, id):
|
||||
return anki.notes.Note(self, id=id)
|
||||
|
@ -767,3 +771,9 @@ and queue = 0""", intTime(), self.usn())
|
|||
self.db.execute("vacuum")
|
||||
self.db.execute("analyze")
|
||||
self.lock()
|
||||
|
||||
# Logging
|
||||
##########################################################################
|
||||
|
||||
def log(self, *args, **kwargs):
|
||||
runHook("log", args, kwargs)
|
||||
|
|
|
@ -71,6 +71,8 @@ defaultConf = {
|
|||
'minSpace': 1, # not currently used
|
||||
'ivlFct': 1,
|
||||
'maxIvl': 36500,
|
||||
# may not be set on old decks
|
||||
'bury': True,
|
||||
},
|
||||
'maxTaken': 60,
|
||||
'timer': 0,
|
||||
|
|
|
@ -225,7 +225,7 @@ class MediaManager(object):
|
|||
nfcFile = unicodedata.normalize("NFC", file)
|
||||
# we enforce NFC fs encoding on non-macs; on macs we'll have gotten
|
||||
# NFD so we use the above variable for comparing references
|
||||
if not isMac:
|
||||
if not isMac and local:
|
||||
if file != nfcFile:
|
||||
# delete if we already have the NFC form, otherwise rename
|
||||
if os.path.exists(nfcFile):
|
||||
|
|
|
@ -69,7 +69,7 @@ insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)""",
|
|||
return joinFields(self.fields)
|
||||
|
||||
def cards(self):
|
||||
return [self.col.getCard(id) for id in self.col.db.list(
|
||||
return [self.col.getCard(id, log=False) for id in self.col.db.list(
|
||||
"select id from cards where nid = ? order by ord", self.id)]
|
||||
|
||||
def model(self):
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from __future__ import division
|
||||
import time, random, itertools
|
||||
import time
|
||||
import random
|
||||
import itertools
|
||||
from operator import itemgetter
|
||||
from heapq import *
|
||||
|
||||
#from anki.cards import Card
|
||||
from anki.utils import ids2str, intTime, fmtTimeSpan
|
||||
from anki.lang import _
|
||||
|
@ -52,6 +55,7 @@ class Scheduler(object):
|
|||
self._haveQueues = True
|
||||
|
||||
def answerCard(self, card, ease):
|
||||
self.col.log()
|
||||
assert ease >= 1 and ease <= 4
|
||||
self.col.markReview(card)
|
||||
if self._burySiblingsOnAnswer:
|
||||
|
@ -139,14 +143,19 @@ order by due""" % self._deckLimit(),
|
|||
def unburyCards(self):
|
||||
"Unbury cards."
|
||||
self.col.conf['lastUnburied'] = self.today
|
||||
self.col.log(
|
||||
self.col.db.list("select id from cards where queue = -2"))
|
||||
self.col.db.execute(
|
||||
"update cards set mod=?,usn=?,queue=type where queue = -2",
|
||||
intTime(), self.col.usn())
|
||||
"update cards set queue=type where queue = -2")
|
||||
|
||||
def unburyCardsForDeck(self):
|
||||
sids = ids2str(self.col.decks.active())
|
||||
self.col.log(
|
||||
self.col.db.list("select id from cards where queue = -2 and did in %s"
|
||||
% sids))
|
||||
self.col.db.execute(
|
||||
"update cards set mod=?,usn=?,queue=type where queue = -2 and did in %s"
|
||||
% ids2str(self.col.decks.active()), intTime(), self.col.usn())
|
||||
% sids, intTime(), self.col.usn())
|
||||
|
||||
# Rev/lrn/time daily stats
|
||||
##########################################################################
|
||||
|
@ -943,12 +952,14 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)"""
|
|||
ids = []
|
||||
return ids
|
||||
# move the cards over
|
||||
self.col.log(deck['id'], ids)
|
||||
self._moveToDyn(deck['id'], ids)
|
||||
return ids
|
||||
|
||||
def emptyDyn(self, did, lim=None):
|
||||
if not lim:
|
||||
lim = "did = %s" % did
|
||||
self.col.log(self.col.db.list("select id from cards where %s" % lim))
|
||||
# move out of cram queue
|
||||
self.col.db.execute("""
|
||||
update cards set did = odid, queue = (case when type = 1 then 0
|
||||
|
@ -1111,6 +1122,7 @@ did = ?, queue = %s, due = ?, mod = ?, usn = ? where id = ?""" % queue, data)
|
|||
self.today = int((time.time() - self.col.crt) // 86400)
|
||||
# end of day cutoff
|
||||
self.dayCutoff = self.col.crt + (self.today+1)*86400
|
||||
self.col.log(self.today, self.dayCutoff)
|
||||
# update all daily counts, but don't save decks to prevent needless
|
||||
# conflicts. we'll save on card answer instead
|
||||
def update(g):
|
||||
|
@ -1239,6 +1251,7 @@ To study outside of the normal schedule, click the Custom Study button below."""
|
|||
|
||||
def suspendCards(self, ids):
|
||||
"Suspend cards."
|
||||
self.col.log(ids)
|
||||
self.remFromDyn(ids)
|
||||
self.removeLrn(ids)
|
||||
self.col.db.execute(
|
||||
|
@ -1247,6 +1260,7 @@ To study outside of the normal schedule, click the Custom Study button below."""
|
|||
|
||||
def unsuspendCards(self, ids):
|
||||
"Unsuspend cards."
|
||||
self.col.log(ids)
|
||||
self.col.db.execute(
|
||||
"update cards set queue=type,mod=?,usn=? "
|
||||
"where queue = -1 and id in "+ ids2str(ids),
|
||||
|
@ -1256,6 +1270,7 @@ To study outside of the normal schedule, click the Custom Study button below."""
|
|||
"Bury all cards for note until next session."
|
||||
cids = self.col.db.list(
|
||||
"select id from cards where nid = ? and queue >= 0", nid)
|
||||
self.col.log(cids)
|
||||
self.removeLrn(cids)
|
||||
self.col.db.execute("""
|
||||
update cards set queue=-2,mod=?,usn=? where id in """+ids2str(cids),
|
||||
|
@ -1266,15 +1281,19 @@ update cards set queue=-2,mod=?,usn=? where id in """+ids2str(cids),
|
|||
|
||||
def _burySiblings(self, card):
|
||||
toBury = []
|
||||
conf = self._newConf(card)
|
||||
buryNew = conf.get("bury", True)
|
||||
nconf = self._newConf(card)
|
||||
buryNew = nconf.get("bury", True)
|
||||
rconf = self._revConf(card)
|
||||
buryRev = rconf.get("bury", True)
|
||||
# loop through and remove from queues
|
||||
for cid,queue in self.col.db.execute("""
|
||||
select id, queue from cards where nid=? and id!=?
|
||||
and (queue=0 or (queue=2 and due<=?))""",
|
||||
card.nid, card.id, self.today):
|
||||
if queue == 2:
|
||||
toBury.append(cid)
|
||||
if buryRev:
|
||||
toBury.append(cid)
|
||||
# if bury disabled, we still discard to give same-day spacing
|
||||
try:
|
||||
self._revQueue.remove(cid)
|
||||
except ValueError:
|
||||
|
@ -1288,9 +1307,11 @@ and (queue=0 or (queue=2 and due<=?))""",
|
|||
except ValueError:
|
||||
pass
|
||||
# then bury
|
||||
self.col.db.execute(
|
||||
"update cards set queue=-2,mod=?,usn=? where id in "+ids2str(toBury),
|
||||
intTime(), self.col.usn())
|
||||
if toBury:
|
||||
self.col.db.execute(
|
||||
"update cards set queue=-2,mod=?,usn=? where id in "+ids2str(toBury),
|
||||
intTime(), self.col.usn())
|
||||
self.col.log(toBury)
|
||||
|
||||
# Resetting
|
||||
##########################################################################
|
||||
|
@ -1304,6 +1325,7 @@ and (queue=0 or (queue=2 and due<=?))""",
|
|||
"select max(due) from cards where type=0") or 0
|
||||
# takes care of mod + usn
|
||||
self.sortCards(ids, start=pmax+1)
|
||||
self.col.log(ids)
|
||||
|
||||
def reschedCards(self, ids, imin, imax):
|
||||
"Put cards in review queue with a new interval in days (min, max)."
|
||||
|
@ -1319,6 +1341,7 @@ and (queue=0 or (queue=2 and due<=?))""",
|
|||
update cards set type=2,queue=2,ivl=:ivl,due=:due,
|
||||
usn=:usn, mod=:mod, factor=:fact where id=:id and odid=0 and queue >=0""",
|
||||
d)
|
||||
self.col.log(ids)
|
||||
|
||||
def resetCards(self, ids):
|
||||
"Completely reset cards for export."
|
||||
|
@ -1328,6 +1351,7 @@ usn=:usn, mod=:mod, factor=:fact where id=:id and odid=0 and queue >=0""",
|
|||
self.col.db.execute(
|
||||
"update cards set reps=0, lapses=0 where id in " + ids2str(nonNew))
|
||||
self.forgetCards(nonNew)
|
||||
self.col.log(ids)
|
||||
|
||||
# Repositioning new cards
|
||||
##########################################################################
|
||||
|
@ -1370,6 +1394,7 @@ and due >= ? and queue = 0""" % scids, now, self.col.usn(), shiftby, low)
|
|||
d.append(dict(now=now, due=due[nid], usn=self.col.usn(), cid=id))
|
||||
self.col.db.executemany(
|
||||
"update cards set due=:due,mod=:now,usn=:usn where id = :cid", d)
|
||||
self.col.log(cids)
|
||||
|
||||
def randomizeCards(self, did):
|
||||
cids = self.col.db.list("select id from cards where did = ?", did)
|
||||
|
|
|
@ -3,11 +3,15 @@
|
|||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
from __future__ import division
|
||||
import time, datetime, json
|
||||
import time
|
||||
import datetime
|
||||
import json
|
||||
|
||||
import anki.js
|
||||
from anki.utils import fmtTimeSpan, ids2str
|
||||
from anki.lang import _, ngettext
|
||||
|
||||
|
||||
# Card stats
|
||||
##########################################################################
|
||||
|
||||
|
@ -56,6 +60,8 @@ class CardStats(object):
|
|||
self.addLine(_("Card Type"), c.template()['name'])
|
||||
self.addLine(_("Note Type"), c.model()['name'])
|
||||
self.addLine(_("Deck"), self.col.decks.name(c.did))
|
||||
self.addLine(_("Note ID"), c.nid)
|
||||
self.addLine(_("Card ID"), c.id)
|
||||
self.txt += "</table>"
|
||||
return self.txt
|
||||
|
||||
|
|
14
anki/sync.py
14
anki/sync.py
|
@ -17,9 +17,12 @@ from hooks import runHook
|
|||
import anki
|
||||
|
||||
# syncing vars
|
||||
HTTP_TIMEOUT = 30
|
||||
HTTP_TIMEOUT = 90
|
||||
HTTP_PROXY = None
|
||||
|
||||
# badly named; means no retries, and doesn't affect ssl connections
|
||||
httplib2.RETRIES = 1
|
||||
|
||||
try:
|
||||
# httplib2 >=0.7.7
|
||||
_proxy_info_from_environment = httplib2.proxy_info_from_environment
|
||||
|
@ -105,6 +108,7 @@ class Syncer(object):
|
|||
# step 1: login & metadata
|
||||
runHook("sync", "login")
|
||||
meta = self.server.meta()
|
||||
self.col.log("rmeta", meta)
|
||||
if not meta:
|
||||
return "badAuth"
|
||||
rscm = meta['scm']
|
||||
|
@ -125,19 +129,24 @@ class Syncer(object):
|
|||
# and require confirmation if it's non-empty
|
||||
pass
|
||||
meta = self.meta()
|
||||
self.col.log("lmeta", meta)
|
||||
self.lmod = meta['mod']
|
||||
self.minUsn = meta['usn']
|
||||
lscm = meta['scm']
|
||||
lts = meta['ts']
|
||||
if abs(rts - lts) > 300:
|
||||
self.col.log("clock off")
|
||||
return "clockOff"
|
||||
if self.lmod == self.rmod:
|
||||
self.col.log("no changes")
|
||||
return "noChanges"
|
||||
elif lscm != rscm:
|
||||
self.col.log("schema diff")
|
||||
return "fullSync"
|
||||
self.lnewer = self.lmod > self.rmod
|
||||
# step 1.5: check collection is valid
|
||||
if not self.col.basicCheck():
|
||||
self.col.log("basic check")
|
||||
return "basicCheckFailed"
|
||||
# step 2: deletions
|
||||
runHook("sync", "meta")
|
||||
|
@ -154,6 +163,7 @@ class Syncer(object):
|
|||
while 1:
|
||||
runHook("sync", "stream")
|
||||
chunk = self.server.chunk()
|
||||
self.col.log("server chunk", chunk)
|
||||
self.applyChunk(chunk=chunk)
|
||||
if chunk['done']:
|
||||
break
|
||||
|
@ -162,6 +172,7 @@ class Syncer(object):
|
|||
while 1:
|
||||
runHook("sync", "stream")
|
||||
chunk = self.chunk()
|
||||
self.col.log("client chunk", chunk)
|
||||
self.server.applyChunk(chunk=chunk)
|
||||
if chunk['done']:
|
||||
break
|
||||
|
@ -478,6 +489,7 @@ from notes where %s""" % d)
|
|||
for r in data:
|
||||
if r[0] not in lmods or lmods[r[0]] < r[modIdx]:
|
||||
update.append(r)
|
||||
self.col.log(table, data)
|
||||
return update
|
||||
|
||||
def mergeCards(self, cards):
|
||||
|
|
|
@ -45,7 +45,7 @@ class DataModel(QAbstractTableModel):
|
|||
def getCard(self, index):
|
||||
id = self.cards[index.row()]
|
||||
if not id in self.cardObjs:
|
||||
self.cardObjs[id] = self.col.getCard(id)
|
||||
self.cardObjs[id] = self.col.getCard(id, log=False)
|
||||
return self.cardObjs[id]
|
||||
|
||||
def refreshNote(self, note):
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||
# -*- coding: utf-8 -*-
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
from anki.consts import NEW_CARDS_RANDOM
|
||||
from operator import itemgetter
|
||||
|
||||
from anki.consts import NEW_CARDS_RANDOM
|
||||
from aqt.qt import *
|
||||
import aqt
|
||||
from aqt.utils import showInfo, showWarning, openHelp, getOnlyText, askUser, \
|
||||
tooltip
|
||||
from operator import itemgetter
|
||||
|
||||
class DeckConf(QDialog):
|
||||
def __init__(self, mw, deck):
|
||||
|
@ -189,6 +189,7 @@ class DeckConf(QDialog):
|
|||
f.fi1.setValue(c['ivlFct']*100)
|
||||
f.maxIvl.setValue(c['maxIvl'])
|
||||
f.revplim.setText(self.parentLimText('rev'))
|
||||
f.buryRev.setChecked(c.get("bury", True))
|
||||
# lapse
|
||||
c = self.conf['lapse']
|
||||
f.lapSteps.setText(self.listToUser(c['delays']))
|
||||
|
@ -270,6 +271,7 @@ class DeckConf(QDialog):
|
|||
c['ease4'] = f.easyBonus.value()/100.0
|
||||
c['ivlFct'] = f.fi1.value()/100.0
|
||||
c['maxIvl'] = f.maxIvl.value()
|
||||
c['bury'] = f.buryRev.isChecked()
|
||||
# lapse
|
||||
c = self.conf['lapse']
|
||||
self.updateList(c, 'delays', f.lapSteps, minSize=0)
|
||||
|
|
46
aqt/main.py
46
aqt/main.py
|
@ -2,20 +2,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import os, sys, re, traceback, signal
|
||||
import os
|
||||
import pprint
|
||||
import sys
|
||||
import re
|
||||
import traceback
|
||||
import signal
|
||||
import zipfile
|
||||
|
||||
from send2trash import send2trash
|
||||
from aqt.qt import *
|
||||
|
||||
from anki import Collection
|
||||
from anki.utils import isWin, isMac, intTime, splitFields, ids2str
|
||||
from anki.hooks import runHook, addHook
|
||||
|
||||
import aqt, aqt.progress, aqt.webview, aqt.toolbar, aqt.stats
|
||||
from anki.hooks import runHook, addHook
|
||||
import aqt
|
||||
import aqt.progress
|
||||
import aqt.webview
|
||||
import aqt.toolbar
|
||||
import aqt.stats
|
||||
from aqt.utils import restoreGeom, showInfo, showWarning,\
|
||||
restoreState, getOnlyText, askUser, applyStyles, showText, tooltip, \
|
||||
openHelp, openLink, checkInvalidFilename
|
||||
|
||||
|
||||
class AnkiQt(QMainWindow):
|
||||
def __init__(self, app, profileManager, args):
|
||||
QMainWindow.__init__(self)
|
||||
|
@ -159,7 +169,6 @@ class AnkiQt(QMainWindow):
|
|||
return True
|
||||
|
||||
def profileNameOk(self, str):
|
||||
from anki.utils import invalidFilename, invalidFilenameChars
|
||||
return not checkInvalidFilename(str)
|
||||
|
||||
def onAddProfile(self):
|
||||
|
@ -261,7 +270,8 @@ To import into a password protected profile, please open the profile before atte
|
|||
showWarning("""\
|
||||
Your collection is corrupt. Please see the manual for \
|
||||
how to restore from a backup.""")
|
||||
return self.unloadProfile()
|
||||
self.unloadProfile()
|
||||
raise
|
||||
self.hideSchemaMsg = False
|
||||
self.progress.setupDB(self.col.db)
|
||||
self.maybeEnableUndo()
|
||||
|
@ -829,6 +839,7 @@ the problem and restart Anki.""")
|
|||
def setupHooks(self):
|
||||
addHook("modSchema", self.onSchemaMod)
|
||||
addHook("remNotes", self.onRemNotes)
|
||||
addHook("log", self.onLog)
|
||||
|
||||
# Log note deletion
|
||||
##########################################################################
|
||||
|
@ -846,6 +857,23 @@ the problem and restart Anki.""")
|
|||
f.write(("\t".join([str(id), str(mid)] + fields)).encode("utf8"))
|
||||
f.write("\n")
|
||||
|
||||
# Debug logging
|
||||
##########################################################################
|
||||
|
||||
def onLog(self, args, kwargs):
|
||||
def customRepr(x):
|
||||
if isinstance(x, basestring):
|
||||
return x
|
||||
return pprint.pformat(x)
|
||||
path, num, fn, y = traceback.extract_stack(
|
||||
limit=4+kwargs.get("stack", 0))[0]
|
||||
buf = u"[%s] %s:%s(): %s" % (intTime(), os.path.basename(path), fn,
|
||||
", ".join([customRepr(x) for x in args]))
|
||||
lpath = re.sub("\.anki2$", ".log", self.pm.collectionPath())
|
||||
open(lpath, "ab").write(buf.encode("utf8") + "\n")
|
||||
if os.environ.get("LOG"):
|
||||
print buf
|
||||
|
||||
# Schema modifications
|
||||
##########################################################################
|
||||
|
||||
|
@ -1051,6 +1079,8 @@ will be lost. Continue?"""))
|
|||
elif isWin:
|
||||
# make sure ctypes is bundled
|
||||
from ctypes import windll, wintypes
|
||||
_dummy = windll
|
||||
_dummy = wintypes
|
||||
|
||||
def maybeHideAccelerators(self, tgt=None):
|
||||
if not self.hideMenuAccels:
|
||||
|
@ -1076,6 +1106,10 @@ will be lost. Continue?"""))
|
|||
self.connect(self.app, SIGNAL("appMsg"), self.onAppMsg)
|
||||
|
||||
def onAppMsg(self, buf):
|
||||
if not isinstance(buf, unicode):
|
||||
# even though we're sending this as unicode up above,
|
||||
# a bug report still came in that we were receiving a qbytearray
|
||||
buf = unicode(buf, "utf8", "ignore")
|
||||
if self.state == "startup":
|
||||
# try again in a second
|
||||
return self.progress.timer(1000, lambda: self.onAppMsg(buf), False)
|
||||
|
|
|
@ -271,13 +271,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="revplim">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="text">
|
||||
|
@ -292,25 +285,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="fi1">
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
|
@ -335,6 +309,39 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="revplim">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="fi1">
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>100.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="buryRev">
|
||||
<property name="text">
|
||||
<string>Bury related reviews until the next day</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -616,6 +623,7 @@
|
|||
<tabstop>easyBonus</tabstop>
|
||||
<tabstop>fi1</tabstop>
|
||||
<tabstop>maxIvl</tabstop>
|
||||
<tabstop>buryRev</tabstop>
|
||||
<tabstop>lapSteps</tabstop>
|
||||
<tabstop>lapMult</tabstop>
|
||||
<tabstop>lapMinInt</tabstop>
|
||||
|
|
Loading…
Reference in a new issue