refactor latex into media support

This commit is contained in:
Damien Elmes 2008-12-23 18:00:12 +09:00
parent 6a21be9d19
commit 3b3fef4ebc
3 changed files with 83 additions and 50 deletions

View file

@ -1940,6 +1940,8 @@ create index if not exists ix_fields_value on fields (value)""")
# media
deck.s.statement("""
create unique index if not exists ix_media_filename on media (filename)""")
deck.s.statement("""
create index if not exists ix_media_originalPath on media (originalPath)""")
# deletion tracking
deck.s.statement("""
create index if not exists ix_cardsDeleted_cardId on cardsDeleted (cardId)""")
@ -2182,6 +2184,7 @@ where interval < 1""")
if deck.version < 18:
deck.version = 18
deck.s.commit()
DeckStorage._addIndices(deck)
deck.s.statement("analyze")
return deck
_upgradeDeck = staticmethod(_upgradeDeck)

View file

@ -8,14 +8,10 @@ Latex support
"""
__docformat__ = 'restructuredtext'
import re, tempfile, os, sys, subprocess
import re, tempfile, os, sys, subprocess, stat, time
from anki.utils import genID, checksum
from anki.media import copyToMedia
from htmlentitydefs import entitydefs
try:
import hashlib
md5 = hashlib.md5
except ImportError:
import md5
md5 = md5.new
latexPreamble = ("\\documentclass[12pt]{article}\n"
"\\special{papersize=3in,5in}"
@ -74,13 +70,14 @@ def call(*args, **kwargs):
break
return ret
def generatedFile(latexCode):
return "%s.png" % md5(latexCode).hexdigest()
def latexImgFile(deck, latexCode):
key = checksum(latexCode)
return deck.s.scalar("select filename from media where originalPath = :k",
k=key)
def generatedPath(deck, latexCode):
def latexImgPath(deck, file):
"Return the path to the cache file in system encoding format."
path = os.path.join(deck.mediaDir(create=True),
generatedFile(latexCode))
path = os.path.join(deck.mediaDir(create=True), file)
return path.encode(sys.getfilesystemencoding())
def mungeLatex(latex):
@ -92,10 +89,23 @@ def mungeLatex(latex):
latex = latex.encode("utf-8")
return latex
def imageForLatex(deck, latex):
"Return an image that represents 'latex', building if necessary."
imagePath = generatedPath(deck, latex)
if not os.path.exists(imagePath):
def deleteAllLatexImages(deck):
for f in deck.s.column0(
"select filename from media where description = 'latex'"):
path = latexImgPath(deck, f)
try:
os.unlink(path)
except (OSError, IOError):
pass
deck.s.statement("delete from media where description = 'latex'")
deck.flushMod()
def cacheAllLatexImages(deck):
fields = deck.s.column0("select value from fields")
for field in fields:
renderLatex(deck, field)
def buildImg(deck, latex):
log = open(os.path.join(tmpdir, "latex_log.txt"), "w+")
texpath = os.path.join(tmpdir, "tmp.tex")
texfile = file(texpath, "w")
@ -118,12 +128,26 @@ def imageForLatex(deck, latex):
if call(["latex", "-interaction=nonstopmode",
texpath], stdout=log, stderr=log, startupinfo=si):
return (False, errmsg)
if call(latexDviPngCmd + ["tmp.dvi", "-o", imagePath],
if call(latexDviPngCmd + ["tmp.dvi", "-o", "tmp.png"],
stdout=log, stderr=log, startupinfo=si):
return (False, errmsg)
# add to media
path = copyToMedia(deck, "tmp.png", latex=checksum(latex))
return (True, path)
finally:
os.chdir(oldcwd)
return (True, imagePath)
def imageForLatex(deck, latex):
"Return an image that represents 'latex', building if necessary."
imageFile = latexImgFile(deck, latex)
if imageFile:
path = latexImgPath(deck, imageFile)
ok = True
if not imageFile or not os.path.exists(path):
(ok, imageFile) = buildImg(deck, latex)
if not ok:
return (False, imageFile)
return (True, imageFile)
def imgLink(deck, latex):
"Parse LATEX and return a HTML image representing the output."

View file

@ -51,9 +51,15 @@ def mediaFilename(path):
ext = os.path.splitext(path)[1].lower()
return "%s%s" % (new, ext)
def copyToMedia(deck, path):
def copyToMedia(deck, path, latex=None):
"""Copy PATH to MEDIADIR, and return new filename.
Update media table. If file already exists, don't copy."""
if latex:
origPath = latex
description = "latex"
else:
origPath = path
description = os.path.splitext(os.path.basename(path))[0]
newBase = mediaFilename(path)
new = os.path.join(deck.mediaDir(create=True), newBase)
# copy if not existing
@ -80,9 +86,9 @@ values (:id, :filename, :size, :created, :originalPath,
filename=newBase,
size=newSize,
created=time.time(),
originalPath=path,
description=os.path.splitext(
os.path.basename(path))[0])
originalPath=origPath,
description=description)
deck.flushMod()
return newBase
def _modifyFields(deck, fieldsToUpdate, modifiedFacts, dirty):
@ -118,8 +124,6 @@ def rebuildMediaDir(deck, deleteRefs=False, dirty=True):
oldPath = os.path.join(deck.mediaDir(), oldBase)
if oldBase.startswith("."):
continue
if oldBase.startswith("latex-"):
continue
if os.path.isdir(oldPath):
continue
newBase = copyToMedia(deck, oldPath)
@ -164,12 +168,14 @@ def rebuildMediaDir(deck, deleteRefs=False, dirty=True):
deck.deleteTags(unmodifiedFacts.keys(), _("Media Missing"))
# build cache of db records
mediaIds = dict(deck.s.all("select filename, id from media"))
# assume latex files exist
for f in deck.s.column0(
"select filename from media where description = 'latex'"):
usedFiles[f] = 1
# look through the media dir for any unused files, and delete
for f in os.listdir(unicode(deck.mediaDir())):
if f.startswith("."):
continue
if f.startswith("latex-"):
continue
path = os.path.join(deck.mediaDir(), f)
if os.path.isdir(path):
shutil.rmtree(path)