"""
/*
* gentabtex.py 1.2
* gentabtex.py: high layer interface for rendering LaTeX tables.
*
* Copyright (C) Manuel Gutierrez Algaba, 2004,
[email protected]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
[email protected]
changes
version : date:
0.1 : March 2004: added automatical balancing of columns.
1.2 : January 2006: added operators todas todasmenos en desdehasta
"""
separador = " }& "
terminador = r"\\" + "\n"
class distribuidor:
class pesocolumna:
def __init__(self):
self.filas = []
def anyadefila(self, fila):
self.filas.append(fila)
def dapeso(self):
s= 0
for i in self.filas:
s += len(i)
return s
def dapesonor(self):
return self. pesonormalizado
def hazpesonor(self, p):
self. pesonormalizado = p
def normalizapeso(self, total, factor):
self.pesonormalizado = factor * ( self.dapeso() * 1.0 / total)
#print "Peso normalizado", self.pesonormalizado, "total ", total, "factor", factor, "peso", self.dapeso(), "relativo", ( self.dapeso() * 1.0 / total)
def __cmp__(self, o):
p= self.dapeso()
po = o.dapeso()
if p<po:
return -1
else:
return 1
def __init__(self):
self.listacolumnas=[]
def anyadecolumna(self):
self.listacolumnas. append( distribuidor.pesocolumna())
def anyadeencolumna(self, fila):
self.listacolumnas[-1].anyadefila(fila)
def calculapesototal(self):
t = 0
for i in self.listacolumnas:
t += i.dapeso()
return t
def calculapesorel(self, lis):
t = 0
for i in lis:
t += i.dapeso()
return t
def calculapeso(self, columna):
return self.listacolumnas[columna].dapeso()
def imprimepesos(self):
print "Imprimiendo pesos"
for i in self.listacolumnas:
print i.dapeso()
def asignapesos(self, anchura=60):
t = self.calculapesototal()
for i in self.listacolumnas:
#print i.dapeso()
i.dapeso()
def repartepesos(self, tamanyototal, tamanyominimo):
l = self.listacolumnas[:]
l.sort()
return self.recrepartepesos1(tamanyototal, tamanyominimo, l )
def recrepartepesos1(self, tamanyototal, tamanyominimo, columnas):
if columnas==[]: return []
total = self. calculapesorel(columnas)
for i in [columnas[0]]:
i. normalizapeso( total, tamanyototal * 1.0)
return self.recrepartepesos( tamanyototal, tamanyominimo, columnas)
def recrepartepesos(self, tamanyototal, tamanyominimo, restante):
"""
"""
pesocolprimera= restante[0].dapesonor()
if pesocolprimera < tamanyominimo:
restante[0]. hazpesonor(tamanyominimo )
return [ tamanyominimo ] + self.recrepartepesos1(tamanyototal - tamanyominimo,
tamanyominimo, restante[1:])
else:
return [pesocolprimera ] + self.recrepartepesos1(tamanyototal - pesocolprimera,
tamanyominimo, restante[1:])
def dapesosformatostex(self):
dev= "{"
for i in self.listacolumnas:
dev += "p{" + "%2.2f" % i.dapesonor() +"cm}"
#print dev
return dev +"}"
class gentabtex:
class matrizdispersa:
"""
a(y,x )
-------> x
!
!
!
!
V
y
"""
def calculapesos(self):
self.dist = distribuidor()
for j in xrange(0, self.dimx()):
self.dist.anyadecolumna()
for i in xrange(0, self.dimy()):
if self.mmatriz. has_key((i,j)):
self.dist.anyadeencolumna(self.mmatriz[(i,j)])
def imprimepesos(self):
self.dist.imprimepesos()
def __init__(self):
self.mmatriz = {}
def anyade(self, posx, posy, el):
self.mmatriz[(posy, posx) ] = el
def __getitem__(self, dupla):
return self.mmatriz[dupla]
def dimx(self):
return max(map( lambda(x):x.__getitem__(1), (self.mmatriz.keys()))) + 1
def dimy(self):
return max(map( lambda(x):x.__getitem__(0), (self.mmatriz.keys()))) + 1
def __str__(self):
#print "Dimensiones", self.dimy(), self.dimx()
a= ""
for i in xrange(0, self.dimy()):
for j in xrange(0, self.dimx()):
if self.mmatriz. has_key((i,j)):
if type(self.mmatriz[(i,j)]) != type(""):
a += str(self.mmatriz[(i,j)])
else:
a += self.mmatriz[(i,j)]
a += separador
a = a[:-(len(separador))]
a += terminador
return a
def imprime(self):
print self.mmatriz
def repartepesos(self, tamanayototal, tamanyominimo):
return self.dist. repartepesos( tamanayototal, tamanyominimo)
def dapesosformatostex(self):
return self. dist. dapesosformatostex()
class filasenorden:
def __init__(self, columna=0):
self.filaorden=1
self.listafilas=[]
self.columna= columna
def anyade(self, t):
self.filaorden += 1
self.listafilas.append(t)
def devnumerofilas(self):
return len(self.listafilas)
def devfila(self, nfila, col):
if col==self.columna:
return self.listafilas[nfila]
def escribeenmatriz(self, matriz):
j = 1
for i in self.listafilas:
matriz. anyade( self.columna, j, i )
j += 1
class columnasenorden:
def __init__(self, fila=0):
self.columnaorden=1
self.listacolumnas=[]
self.fila= fila
def anyade(self, t):
self.columnaorden += 1
self.listacolumnas.append(t)
def devnumerocolumnas(self):
return len(self.listacolumnas)
def devcolumna(self, nfila, col):
if nfila==self.fila:
return self.listacolumnas[col]
def escribeenmatriz(self, matriz):
j = 0
for i in self.listacolumnas:
matriz. anyade( j, self.fila, i )
j += 1
class cequis:
def __init__(self, columna, filas, columnanum=None, extendido= None):
self.columna = columna
self.filas = filas
self. columnanum = columnanum
self. extendido = extendido
def escribeenmatriz(self, matriz):
if self.columna=="ultimacolumna":
self.escribe1(matriz)
else:
if not self. columnanum is None:
self. escribe2(matriz)
elif self.columna == "todafila":
#return
for i in xrange(0,matriz.dimy()):
puedeescribir = 0
#print self.extendido, self.filas
for j in self.filas:
if self.esvalido(j, (i,0), matriz):
puedeescribir = 1
break
if puedeescribir:
for c in xrange(1, matriz.dimx()):
matriz.anyade( c, i, 'x')
#print "trastodafila" , matriz
def escribe2(self, matriz):
def esextendidovalido(matriz, i):
for j in self. extendido:
if self.esvalido( j, (i, 0), matriz ):
return 1
c= self. columnanum - 1
if self.filas == "todas" or self.filas=="toda":
for i in xrange(1,matriz.dimy()):
matriz.anyade( c + 1, i , 'x')
if self.filas == "todamenos" or self.filas=="todasmenos":
for i in xrange(1,matriz.dimy()):
puedeescribir = 1
#print self.extendido
for j in self. extendido:
if self.esvalido( j, (i, 0), matriz ):
puedeescribir = 0
if puedeescribir:
matriz.anyade( c+1, i, 'x')
elif self.filas=="desdehasta":
#print "desdehasta"
def escribetramovalido(matriz, j,c):
for k in xrange(j, matriz.dimy()):
matriz.anyade( c+1, k, 'x')
if esextendidovalido(matriz, k):
break
for i in xrange(0,matriz.dimy()):
#print self.extendido
if esextendidovalido( matriz, i):
matriz.anyade( c+1, i, 'x')
escribetramovalido(matriz, i+1, c)
break
elif self.filas=="en":
for i in xrange(0,matriz.dimy()):
puedeescribir = 0
for j in self. extendido:
if self.esvalido( j, (i, 0), matriz ):
puedeescribir = 1
if puedeescribir:
matriz.anyade( c+1, i, 'x')
def esvalido(self, duplacond, duplacoor, matriz):
""" duplacond es de la forma:
('c', 'subcarpeta')
duplacoor:
(0, 1) (y, x)
matriz:{(9, 0): 'Eliminar subcarpetas y archivos', (8, 0): 'Atributos extendidos de escritorio', (3, 0): 'Atributos de lectura' ... }
Se trata de decidir si en matriz, en la posicion (0,1) hay un texto que
contenga la cadena 'subcarpeta'
"""
try:
s = matriz[duplacoor]
except KeyError:
return 0
#matriz.imprime()
#print "duplacond", str(s), duplacond, duplacoor
if duplacond[0]=='c' and type(s)==type(""):
return s.find(duplacond[1] )!=-1
def escribe1(self, matriz):
c = matriz.dimx() - 1
j = 1
for i in self.filas:
matriz.anyade(c, j, i)
j +=1
class ccabecera:
def __init__(self, lista ):
self.lista= lista
def escribeenmatriz(self, matriz):
j = 0
#print len(self.lista)
for i in self.lista :
matriz. anyade( j, 0, i )
j +=1
def ncolumnas(self):
return len(self.lista)
def __init__(self):
self.lamatrizdispersa= gentabtex.matrizdispersa()
self. ofilasenorden = gentabtex.filasenorden()
self. todasfilasenorden = [ self. ofilasenorden ]
self. todosequis = []
self. ocolumnasenorden = gentabtex.columnasenorden()
self. todascolumnasenorden = [ self. ocolumnasenorden ]
self. aspcab =""
self. acoletilla=""
def coletilla(self, colt):
self. acoletilla = colt
return self
def sync(self):
for i in self. todasfilasenorden:
i. escribeenmatriz(self. lamatrizdispersa)
for i in self. todascolumnasenorden:
i. escribeenmatriz(self. lamatrizdispersa)
self.ocabecera. escribeenmatriz(self. lamatrizdispersa)
for i in self. todosequis:
i. escribeenmatriz(self. lamatrizdispersa
)
return self
def __str__(self):
if self.aspcab=="":
self.aspcab="{" + "l" * self. lamatrizdispersa.dimx() +"}"
a=r"""\begin{tabular}""" + self.aspcab + "\n"
a += str(self. lamatrizdispersa)
a+= r"""\end{tabular}"""
a+=self. acoletilla
return a
def imprimepesos(self):
self. lamatrizdispersa. imprimepesos()
def otrafilaenorden(self,col):
self. ofilasenorden = gentabtex.filasenorden(col)
self. todasfilasenorden. append(self. ofilasenorden)
return self
def otracolumnaenorden(self,col):
self. ocolumnasenorden = gentabtex.columnasenorden(col)
self. todascolumnasenorden. append(self. ocolumnasenorden)
return self
def otraen(self, columna):
return self. otrafilaenorden(columna)
def columnas(self, acolumna ):
self. ofilasenorden. columna= acolumnas
return self
def co(self, acolumna):
return self. columnas(acolumna)
def anchuras(self, nanchuras ):
self.nanchuras = anchuras
return self
def enfilaorden(self, dato):
self. ofilasenorden.anyade(dato)
return self
def encolumnaorden(self,dato):
self. ocolumnasenorden.anyade(dato)
return self
def en(self, dato):
if type(dato) == type([]):
for i in dato:
self.enfilaorden(i)
return self
else:
return self. enfilaorden(dato)
def fil(self, dato):
if type(dato) == type([]):
for i in dato:
self.encolumnaorden(i)
self. otracolumnaenorden(self. ocolumnasenorden.fila + 1)
return self
else:
return self. encolumnaorden(dato)
def cabecera(self, listacab):
self.ocabecera= gentabtex.ccabecera(listacab)
return self
def cab(self,listacab):
return self.cabecera(listacab)
def equis(self, columna, filas, extendido=None):
if type(columna)==type(1):
self.todosequis.append(gentabtex.cequis(None, filas, columnanum=columna, extendido=extendido))
else:
self.todosequis.append(gentabtex.cequis(columna, filas))
return self
def defaspectocolumna(self, asp):
"""
{p{2cm}p{2cm}p{0.5cm}p{0.5cm}p{0.5cm}p{0.5cm}}
"""
self. aspcab = asp
return self
def daaspectautoma(self):
self. aspcab = self. lamatrizdispersa. dapesosformatostex()
return self
def repartepesos(self, tamanyototal, tamanyominimo):
self. lamatrizdispersa. repartepesos(tamanyototal, tamanyominimo)
return self
def calculapesos(self):
self. lamatrizdispersa. calculapesos()
return self
if __name__=='__main__':
import sys
f=open("tablasejemplo.tex", "w")
#sys.stdout=f
separador = " & "
g = gentabtex().en("rojo").en("azul").en("verde").en("amarillo"). \
cab(["colores", "buen gusto", "coche", "gallumbos", "fruta"]).otraen(1). \
en(["es dificil conseguir algo que no sobresalte y quede bien",
"los pantalones, camisas, color discreto donde los haya",
"si no es fuerte o amerillento",
"hortero en la mayoria de las ocasiones"]).otraen(2).\
en(["implica conduccion agresiva",
"es un color que como tal rara vez se da, es mas corriente en los nortes",
"no esta de moda",
"es el color que mejor se ve"]).\
equis("ultimacolumna", ["tomate", "alga", "melon", "melon"]).\
defaspectocolumna("")
g.sync()
print g
print r"\\"
g. lamatrizdispersa. calculapesos()
#g.imprimepesos()
g.repartepesos(8, 0.3)
g. daaspectautoma()
print g
print r"\\"
g2 = gentabtex().en(["Recorrer carpetas/Ejecutar archivo",
"Listar carpeta/Leer datos",
"Atributos de lectura", "Atributos extendidos de lectura",
"Crear archivos/Escribir datos", "Crear carpetas/Anexar datos",
"Atributos de escritura", "Atributos extendidos de escritura",
"Eliminar subcarpetas y archivos", "Eliminar",
"Permisos de lectura", "Cambiar permisos",
"Tomar posesi�n", "Sincronizar"]).\
cab([0,1,2,3,4,5,6]). \
equis(1, "toda").equis(2, "todamenos", [('c', 'subcarpeta'),
('c', 'Cambiar permisos')]).\
equis("todafila", [('c', 'Permisos de lectura'),
('c', 'Sincronizar')]).\
equis(3, "desdehasta", (('c',"Recorrer"),('c', "extendidos"))).\
equis(4, "desdehasta", (('c',"Recorrer"),('c', "extendidos"))).\
equis(5, "desdehasta", (('c',"Listar"),('c', "extendidos"))).\
equis(5, "en", [('c',"extendidos de escritura")]).\
equis(6, "desdehasta", (('c',"Crear archivos"),('c', "Atributos de escritura"))).\
coletilla("""\\\\
1 control total
2 modificar
3 leer y ejecutar
4 listar el contenido de la carpeta
5 lectura
6 escribir
""").\
sync()
# daaspectautoma()
#calculapesos(). repartepesos(6, 0.5).
print g2
#print r"\\"
tabcabtec = gentabtex().cab(["Protocolo", "Velocidad nominal",
"Frecuencia base", "Capacidad exigible al cable",
"Categor�a de cable requerida"]).\
fil([ "10Base-T", "10 Mbps", "10 MHz", "10 MHz", "Cat-3"]).\
fil(["100Base-T4", "100 Mbps", "12.5 MHz", "12.5 MHz", "Cat-3"]).\
fil(["802.12 (VG)", "100 Mbps", "15 MHz", "15 MHz", "Cat-3"]).\
fil(["100Base-TX", "100 Mbps", "31.25 MHz", "80 MHz", "Cat-5"]).\
fil(["FDDI (*)", "100 Mbps", "31.25 MHz", "80 MHz", "Cat-5"]).\
fil(["ATM (**)", "155 Mbps", "77.5 MHz", "100 MHz", "Cat-5"]).\
sync().calculapesos().repartepesos(6, 0.5). daaspectautoma()
print tabcabtec
f.close()