summaryrefslogtreecommitdiffstats
path: root/equations
diff options
context:
space:
mode:
authorbnewbold <bnewbold@manus.(none)>2007-07-12 00:59:01 -0400
committerbnewbold <bnewbold@manus.(none)>2007-07-12 00:59:01 -0400
commit39d2613b75160a47a93df560d51b30854249ce9d (patch)
tree49af0dc237016f068b764a5623e2d31836c2bc6e /equations
parente152d2f2d1e257b1ec51adb3640e350207fda77d (diff)
downloadequator-39d2613b75160a47a93df560d51b30854249ce9d.tar.gz
equator-39d2613b75160a47a93df560d51b30854249ce9d.zip
almost working again
Diffstat (limited to 'equations')
-rw-r--r--equations/models.py119
-rw-r--r--equations/signals.py65
-rw-r--r--equations/templates/equations/equation_detail.html27
-rw-r--r--equations/templates/equations/equation_list.html24
-rw-r--r--equations/views.py31
5 files changed, 264 insertions, 2 deletions
diff --git a/equations/models.py b/equations/models.py
index 71a8362..6791eb2 100644
--- a/equations/models.py
+++ b/equations/models.py
@@ -1,3 +1,120 @@
from django.db import models
+from django.utils.translation import gettext_lazy as _
+import django.contrib.auth.models as auth
+from django.conf import settings
+from django.dispatch import dispatcher
+from django.db.models import signals
+from signals import update_render
-# Create your models here.
+class Symbol(models.Model):
+ name = models.CharField(_("Name"), maxlength=256)
+ latex = models.TextField(_("Raw LaTeX"), unique=True)
+ unicode = models.TextField(_("Unicode Representation"), blank=True)
+ renderdir = "symbolrenders/"
+ render = models.ImageField(_("Rendered Image"),
+ upload_to=renderdir, editable=False)
+
+ class Meta:
+ get_latest_by = 'name'
+ class Admin:
+ ordering = ['name']
+
+ def __str__(self):
+ return self.name
+ def get_absolute_url(self):
+ return "/symbol/%s/" % self.id
+ def get_admin_url(self):
+ return "/admin/symbols/%s/" % self.id
+ #def save(self):
+ # super(Symbol, self)
+ # self.update_generic_variable()
+ def save(self):
+ super(Symbol, self).save()
+ self.render = self.renderdir + "%s.png" % self.id
+ super(Symbol, self).save()
+
+def update_generic_variable(sender, instance, signal, *args, **kwargs):
+ """Checks if there is a generic variable associated with this
+ symbol; create one if there isn't"""
+ for v in Variable.objects.filter(isgeneric=True):
+ if v.latex == instance.latex:
+ return
+ genericv = Variable(name="Generic %s" % instance.name,
+ latex=instance.latex,
+ unicode=instance.unicode,
+ symbol=instance,
+ isgeneric=True)
+ genericv.save()
+
+dispatcher.connect(update_render, signal=signals.pre_save, sender=Symbol)
+dispatcher.connect(update_generic_variable, signal=signals.post_save,
+ sender=Symbol)
+
+class Variable(models.Model):
+ name = models.CharField(_("Name"), maxlength=256)
+ latex = models.TextField(_("Raw LaTeX"), unique=True)
+ unicode = models.TextField(_("Unicode Representation"), blank=True)
+ description = models.TextField(_("Description"), blank=True)
+ renderdir = "variablerenders/"
+ render = models.ImageField(_("Rendered Image"),
+ upload_to=renderdir, editable=False)
+ reference = models.URLField(_("Reference URL"), blank=True)
+ symbol = models.ForeignKey(Symbol, verbose_name=_("Symbol"))
+ isgeneric = models.BooleanField(_("Is Generic?"), default=False)
+
+ class Meta:
+ get_latest_by = 'name'
+ class Admin:
+ ordering = ['name']
+
+ def __str__(self):
+ return self.name
+ def get_absolute_url(self):
+ return "/variable/%s/" % self.id
+ def get_admin_url(self):
+ return "/admin/variables/%s/" % self.id
+ def save(self):
+ super(Variable, self).save()
+ self.render = self.renderdir + "%s.png" % self.id
+ super(Variable, self).save()
+
+dispatcher.connect(update_render, signal=signals.pre_save, sender=Variable)
+
+class Equation(models.Model):
+ name = models.CharField(_("Name"), maxlength=256)
+ latex = models.TextField(_("Raw LaTeX"), unique=True)
+ unicode = models.TextField(_("Unicode Representation"), blank=True)
+ description = models.TextField(_("Description"), blank=True)
+ created = models.DateField(_("Created"), auto_now_add=True)
+ updated = models.DateField(_("Last Updated"), auto_now_add=True)
+ owner = models.ForeignKey(auth.User, verbose_name=_("Owner"))
+ variables = models.ManyToManyField(Variable, verbose_name="Variables",
+ editable=True)
+ renderdir = "equationrenders/"
+ render = models.ImageField(_("Rendered Image"),
+ upload_to=renderdir, editable=False)
+ reference = models.URLField(_("Reference URL"), blank=True)
+
+ class Meta:
+ get_latest_by = 'created'
+ class Admin:
+ ordering = ['created']
+
+ def __str__(self):
+ return self.name
+ def get_absolute_url(self):
+ return "/equation/%s/" % self.id
+ def get_admin_url(self):
+ return "/admin/equations/%s/" % self.id
+ def update_variables(self):
+ """Updates the variables field with all Variable objects found
+ in the LaTeX representation."""
+ pass # TODO: write
+ def save(self):
+ self.update_variables()
+ super(Equation, self).save()
+ self.render = self.renderdir + "%s.png" % self.id
+ super(Equation, self).save()
+
+
+dispatcher.connect(update_render, signal=signals.post_save, sender=Equation)
diff --git a/equations/signals.py b/equations/signals.py
new file mode 100644
index 0000000..0fecc34
--- /dev/null
+++ b/equations/signals.py
@@ -0,0 +1,65 @@
+from django.conf import settings
+
+def update_render(sender, instance, signal, *args, **kwargs):
+ """Renders an object's .png representation using LaTeX and puts it
+ in the right directory. Requires latex, dvipng, etc"""
+ import os, shutil, tempfile, subprocess
+ def call_command_in_dir(app, args, targetdir):
+ cwd = os.getcwd()
+ try:
+ os.chdir(targetdir)
+ p = subprocess.Popen(app + ' ' + ' '.join(args), shell=True)
+ sts = os.waitpid(p.pid, 0)
+ # FIXME -- should we raise an exception of status is non-zero?
+ finally:
+ # Restore working directory
+ os.chdir(cwd)
+
+ rawlatex = instance.latex
+ dstdir = settings.MEDIA_ROOT + instance.renderdir
+ dstfile = "%s.png" % instance.id
+ dst = "%s" % instance.id
+
+ prologue = ""
+ latex_template = r'''
+ \documentclass[12pt]{article}
+ \pagestyle{empty}
+ %(prologue)s
+ \begin{document}
+ $$%(raw)s$$
+ \end{document}
+ '''
+ max_pages = 1
+ MAX_RUN_TIME = 5 # seconds
+ latex = "latex"
+ dvipng = "dvipng"
+ latex_args = ("--interaction=nonstopmode", "%s.tex")
+ dvipng_args = ("-q", "-bgTransparent", "-Ttight", "--noghostscript",
+ "-l%s" % max_pages, "%s.dvi")
+ tex = latex_template % { 'raw': rawlatex, 'prologue': prologue }
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ data = open("%s/%s.tex" % (tmpdir, dst), "w")
+ data.write(tex)
+ data.close()
+ args = list(latex_args)
+ args[-1] = args[-1] % dst
+ res = call_command_in_dir(latex, args, tmpdir)
+ if not res is None:
+ # FIXME need to return some sort of error
+ return []
+ args = list(dvipng_args)
+ args[-1] = args[-1] % dst
+ res = call_command_in_dir(dvipng, args, tmpdir)
+ if not res is None:
+ # FIXME need to return some sort of error
+ return []
+
+ if os.access("%s/%s1.png" % (tmpdir, dst), os.R_OK):
+ shutil.copyfile("%s/%s1.png" % (tmpdir, dst),
+ dstdir + dstfile)
+ finally:
+ # FIXME do some tidy up here
+ instance.render = instance.renderdir + dstfile
+ shutil.rmtree(tmpdir)
diff --git a/equations/templates/equations/equation_detail.html b/equations/templates/equations/equation_detail.html
new file mode 100644
index 0000000..b4c3911
--- /dev/null
+++ b/equations/templates/equations/equation_detail.html
@@ -0,0 +1,27 @@
+{% extends "base.html" %}
+
+{% block title %}{{ object.name }}{% endblock %}
+
+{% block content %}
+<div style="width: 100px; text-align:center;">
+<img src="{{ object.get_render_url }}" style="border: none;" /></div>
+<table width="100%">
+{% if object.description %}
+ <tr><td><b>Description:</b></td><td>{{ object.description }}</td></tr>
+{% endif %}
+{% if object.variables %}
+ <tr><td><b>Variables:</b></td><td>
+ {% for variable in object.variables %}
+ <a href="{{ variable.get_absolute_url }}">{{ variable.name }}</a><br />
+ {% endfor %}
+{% endif %}
+ <tr><td><b>Raw LaTeX:</b></td><td>{{ object.latex }}</td></tr>
+{% if object.unicode %}
+ <tr><td><b>Unicode:</b></td><td>{{ object.unicode }}</td></tr>
+{% endif %}
+ <tr><td></td><td><br />
+ This equation was created on <i>{{ object.created }}</i>;
+ it was last updated on <i>{{ object.updated }}</i>. It's owner is
+ <i>{{ object.owner }}</i>.</td></tr>
+</table>
+{% endblock %}
diff --git a/equations/templates/equations/equation_list.html b/equations/templates/equations/equation_list.html
new file mode 100644
index 0000000..c7a9632
--- /dev/null
+++ b/equations/templates/equations/equation_list.html
@@ -0,0 +1,24 @@
+{% extends "base.html" %}
+
+{% block title %}Check out all these equations!{% endblock %}
+
+{% block content %}
+{% if object_list %}
+<table width="!00%">
+ {% for item in object_list %}
+ <tr style="height:50px;"><td style="width:45%;">
+ <a href="{{ item.get_absolute_url }}" class="imglink">
+ <img style="border: none;" src="{{ item.get_render_url }}" /></a>
+ </td><td style="width: 55%"><a href="{{ item.get_absolute_url }}">
+ {{ item.name }}</a></td></tr>
+ {% endfor %}
+</table>
+{% if not is_paginated %}<br />{% if not has_previous %}
+<b><a href="./?page={{ previous }}" style="float:left;">&lt;PREV</a></b>
+{% endif %}{% if has_next %}
+<b><a href="./?page={{ next }}" style="float:right;">NEXT&gt;</a></b>
+{% endif %}{% endif %}
+{% else %}
+Fuck, where are they?
+{% endif %}
+{% endblock %}
diff --git a/equations/views.py b/equations/views.py
index 60f00ef..8e2f6fa 100644
--- a/equations/views.py
+++ b/equations/views.py
@@ -1 +1,30 @@
-# Create your views here.
+from django.core import serializers
+from models import Equation, Variable, Symbol
+from django.http import HttpResponse
+
+def all_vars(request):
+ data = serializers.serialize("json", Variable.objects.all())
+ return HttpResponse(data, mimetype="text/javascript")
+
+def all_symbs(request):
+ data = serializers.serialize("json", Symbol.objects.all())
+ return HttpResponse(data, mimetype="text/javascript")
+
+def equs_by_vars(request, whichvars):
+ vars = whichvars.split(',')
+ if len(vars) < 1:
+ return HttpResponse('[]', mimetype="text/javascript")
+ #if vars[-1] == '/':
+ # vars = vars[:-1]
+ returnables = Equation.objects.filter(variables=vars[0])
+ if len(vars) > 1:
+ for r in returnables:
+ for i in vars[1:]:
+ if not i in r.variables:
+ returnables = returnables.exclude(id=r.id)
+ if len(returnables) < 1:
+ break
+
+ data = serializers.serialize("json", returnables)
+ return HttpResponse(data, mimetype="text/javascript")
+