Codebase list anki / 576eb7a
New upstream version 2.1.6+dfsg Julian Gilbey 5 years ago
76 changed file(s) with 54 addition(s) and 31 deletion(s). Raw diff Collapse all Expand all
1212 Anki requires:
1313
1414 - Python 3.6+
15 - Qt 5.9.x and a PyQT that supports it
15 - Qt 5.9.x/5.11.x/5.12.x and a PyQT that supports it
1616 - mpv
1717 - lame
1818
2020
2121 $ pip3 install -r requirements.txt
2222
23 If you're on a Linux distribution that packages PyQt 5.9 then you can use the
24 distro's packages. Make sure you install the development tools (eg
23 If you're on a Linux distribution that packages a compatible Qt then you can
24 use the distro's packages. Make sure you install the development tools (eg
2525 pyqt5-dev-tools) as well.
2626
2727 If you're on another platform or your distro has the wrong Qt version, you
2828 can install PyQt with pip:
2929
30 $ pip3 install sip pyqt5==5.9
30 $ pip3 install sip pyqt5
3131
3232 To use the development version:
3333
99 if sys.getfilesystemencoding().lower() in ("ascii", "ansi_x3.4-1968"):
1010 raise Exception("Anki requires a UTF-8 locale.")
1111
12 version="2.1.6-beta2" # build scripts grep this line, so preserve formatting
12 version="2.1.6" # build scripts grep this line, so preserve formatting
1313 from anki.storage import Collection
1414 __all__ = ["Collection"]
439439 # nothing has that field
440440 return
441441 # gather nids
442 regex = re.escape(val).replace("_", ".").replace("\\%", ".*")
442 regex = re.escape(val).replace("_", ".").replace(re.escape("%"), ".*")
443443 nids = []
444444 for (id,mid,flds) in self.col.db.execute("""
445445 select id, mid, flds from notes
433433 # Learning queues
434434 ##########################################################################
435435
436 # scan for any newly due learning cards every 5 minutes
436 # scan for any newly due learning cards every minute
437437 def _updateLrnCutoff(self, force):
438438 nextCutoff = intTime() + self.col.conf['collapseTime']
439 if nextCutoff - self._lrnCutoff > 300 or force:
439 if nextCutoff - self._lrnCutoff > 60 or force:
440440 self._lrnCutoff = nextCutoff
441441 return True
442442 return False
55 import re
66
77 from anki.lang import _
8 from anki.utils import intTime, json
8 from anki.utils import intTime, json, isWin
99 from anki.db import DB
1010 from anki.collection import _Collection
1111 from anki.consts import *
1212 from anki.stdmodels import addBasicModel, addClozeModel, addForwardReverse, \
1313 addForwardOptionalReverse, addBasicTypingModel
1414
15 def Collection(path, lock=True, server=False, sync=True, log=False):
15 def Collection(path, lock=True, server=False, log=False):
1616 "Open a new or existing collection. Path must be unicode."
1717 assert path.endswith(".anki2")
1818 path = os.path.abspath(path)
2929 else:
3030 ver = _upgradeSchema(db)
3131 db.execute("pragma temp_store = memory")
32 if sync:
33 db.execute("pragma cache_size = 10000")
32 db.execute("pragma cache_size = 10000")
33 if not isWin:
3434 db.execute("pragma journal_mode = wal")
35 else:
36 db.execute("pragma synchronous = off")
3735 db.setAutocommit(False)
3836 # add db to col and do any remaining upgrades
3937 col = _Collection(db, server, log)
4848 # -- setting silentlyClose=True to have it close immediately
4949 # -- define a closeWithCallback() method
5050 # - have the window opened via aqt.dialogs.open(<name>, self)
51 # - have a method reopen(*args), called if the user ask to open the window a second time. Arguments passed are the same than for original opening.
5152
5253 #- make preferences modal? cmd+q does wrong thing
5354
7374 instance.setWindowState(instance.windowState() & ~Qt.WindowMinimized)
7475 instance.activateWindow()
7576 instance.raise_()
77 if hasattr(instance,"reopen"):
78 instance.reopen(*args)
7679 return instance
7780 else:
7881 instance = creator(*args)
22 # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
33
44 from aqt.qt import *
5 from aqt.utils import tooltip
56 import aqt.editor
67 from aqt.utils import saveGeom, restoreGeom
78 from anki.hooks import addHook, remHook
89 from anki.utils import isMac
10
911
1012 class EditCurrent(QDialog):
1113
3335 def onReset(self):
3436 # lazy approach for now: throw away edits
3537 try:
36 n = self.mw.reviewer.card.note()
37 n.load()
38 n = self.editor.note
39 n.load()#reload in case the model changed
3840 except:
3941 # card's been deleted
4042 remHook("reset", self.onReset)
4547 return
4648 self.editor.setNote(n)
4749
50 def reopen(self,mw):
51 tooltip("Please finish editing the existing card first.")
52 self.onReset()
53
4854 def reject(self):
4955 self.saveAndClose()
5056
3434 html { background: %s; }
3535 #topbuts { background: %s; }
3636 </style>
37 <div id="topbuts">%s</div>
37 <div id="topbutsOuter"><div id="topbuts" class="clearfix">%s</div></div>
3838 <div id="fields"></div>
3939 <div id="dupes" style="display:none;"><a href="#" onclick="pycmd('dupes');return false;">%s</a></div>
4040 """
9797 righttopbtns = runFilter("setupEditorButtons", righttopbtns, self)
9898 topbuts = """
9999 <div id="topbutsleft" style="float:left;">
100 <button onclick="pycmd('fields')">%(flds)s...</button>
101 <button onclick="pycmd('cards')">%(cards)s...</button>
100 <button title='%(fldsTitle)s' onclick="pycmd('fields')">%(flds)s...</button>
101 <button title='%(cardsTitle)s' onclick="pycmd('cards')">%(cards)s...</button>
102102 </div>
103103 <div id="topbutsright" style="float:right;">
104104 %(rightbts)s
105105 </div>
106 """ % dict(flds=_("Fields"), cards=_("Cards"), rightbts="".join(righttopbtns))
106 """ % dict(flds=_("Fields"), cards=_("Cards"), rightbts="".join(righttopbtns),
107 fldsTitle=_("Customize Fields"),
108 cardsTitle=shortcut(_("Customize Card Templates (Ctrl+L)")))
107109 bgcol = self.mw.app.palette().window().color().name()
108110 # then load page
109111 self.web.stdHtml(_html % (
335335 return
336336 mw.progress.start(immediate=True)
337337 try:
338 importer.run()
338 try:
339 importer.run()
340 finally:
341 mw.progress.finish()
339342 except zipfile.BadZipfile:
340343 showWarning(invalidZipMsg())
341344 except Exception as e:
359362 tooltip(log)
360363 else:
361364 showText(log)
362 finally:
363 mw.progress.finish()
364365 mw.reset()
365366
366367 def invalidZipMsg():
424424
425425 path = self._glPath()
426426 if not os.path.exists(path):
427 return "software"
427 if qtminor >= 12:
428 return "auto"
429 else:
430 return "software"
428431
429432 mode = open(path, "r").read().strip()
430433
55 overflow-wrap: break-word;
66 }
77
8 /* prevent floated images from being displayed outside field */
9 .field:after {
8 .clearfix:after {
109 content: "";
11 display: block;
12 height: 0;
10 display: table;
1311 clear: both;
14 visibility: hidden;
1512 }
1613
1714 .fname {
2724 margin: 5px;
2825 }
2926
30 #topbuts {
27 #topbutsOuter {
3128 position: fixed;
3229 height: 24px;
3330 top: 0;
3936 .topbut {
4037 width: 16px;
4138 height: 16px;
39 margin-top: 4px;
4240 }
4341
4442 .rainbow {
296296 }
297297 txt += "<tr><td class=fname>{0}</td></tr><tr><td width=100%>".format(n);
298298 txt += "<div id=f{0} onkeydown='onKey();' oninput='onInput()' onmouseup='onKey();'".format(i);
299 txt += " onfocus='onFocus(this);' onblur='onBlur();' class=field ";
299 txt += " onfocus='onFocus(this);' onblur='onBlur();' class='field clearfix' ";
300300 txt += "ondragover='onDragOver(this);' onpaste='onPaste(this);' ";
301301 txt += "oncopy='onCutOrCopy(this);' oncut='onCutOrCopy(this);' ";
302302 txt += "contentEditable=true class=field>{0}</div>".format(f);
445445 node.removeAttributeNode(toRemove[i]);
446446 }
447447 }
448 };
449
450 var adjustFieldsTopMargin = function() {
451 var topHeight = $("#topbuts").height();
452 var margin = topHeight + 8;
453 document.getElementById("fields").style.marginTop = margin + "px";
448454 };
449455
450456 var mouseDown = 0;
476482 $("button.linkb").on("mousedown", function (e) {
477483 e.preventDefault();
478484 });
485
486 window.onresize = function() {
487 adjustFieldsTopMargin();
488 };
489
490 adjustFieldsTopMargin();
479491 });