Scoremanager: pdf_views
This commit is contained in:
committed by
Martin Bauer
parent
7ad5ec21fc
commit
5a3d739a9b
221
scoremanager/pdf_views.py
Normal file
221
scoremanager/pdf_views.py
Normal file
@@ -0,0 +1,221 @@
|
||||
# ----------------------------- Pdf Views ------------------------------------------
|
||||
|
||||
from django.http import HttpResponse
|
||||
from scoremanager.models import Piece
|
||||
|
||||
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Flowable, Table, PageBreak, NextPageTemplate
|
||||
from reportlab.lib import pagesizes, units, utils
|
||||
from reportlab.lib.colors import Color
|
||||
|
||||
import os
|
||||
|
||||
class RepertoireDocTemplate( BaseDocTemplate ):
|
||||
def __init__(self, *args, **kwargs ):
|
||||
BaseDocTemplate.__init__(self,*args, **kwargs)
|
||||
|
||||
self.pagesize = kwargs['pagesize']
|
||||
|
||||
leftBorder = 1 * units.cm
|
||||
rightBorder = 1 * units.cm
|
||||
topBorder = 3 * units.cm
|
||||
bottomBorder = 1 * units.cm
|
||||
|
||||
frameWidth = (self.pagesize[0] - rightBorder - leftBorder ) /2
|
||||
frameHeight = (self.pagesize[1] - topBorder - bottomBorder )
|
||||
|
||||
leftColumn = Frame( leftBorder, bottomBorder, frameWidth, frameHeight, showBoundary=0 )
|
||||
rightColumn = Frame( leftBorder+frameWidth , bottomBorder, frameWidth, frameHeight, showBoundary=0 )
|
||||
|
||||
tocTemplate = PageTemplate( id='TOC', frames=[leftColumn,rightColumn], onPage=RepertoireDocTemplate._drawHeader )
|
||||
fullPageTemplate = PageTemplate( id='FullPage', frames = [ Frame(0,0, self.pagesize[0], self.pagesize[1] ) ] )
|
||||
|
||||
self.addPageTemplates( [ tocTemplate, fullPageTemplate ] )
|
||||
|
||||
@staticmethod
|
||||
def _drawHeader(canvas,document):
|
||||
|
||||
currentPath = os.path.dirname(os.path.realpath(__file__))
|
||||
logoImageFile = currentPath + "/static/pdfImg/logo.png"
|
||||
bgImageFile = currentPath + "/static/pdfImg/body_bg.jpg"
|
||||
|
||||
#Gradient
|
||||
titleAreaHeight = 2 * units.cm
|
||||
gradientColors = [ Color(0.1,0.1,0.1), Color(0.2,0.2,0.2)]
|
||||
ps = document.pagesize
|
||||
gradientStart = ( ps[0]/2, ps[1] )
|
||||
gradientEnd = ( ps[0]/2, ps[1] - titleAreaHeight)
|
||||
canvas.linearGradient( gradientStart[0],gradientStart[1], gradientEnd[0], gradientEnd[1],gradientColors, extend=False )
|
||||
titleAreaMidY = 0.5 * ( gradientStart[1] + gradientEnd[1] )
|
||||
|
||||
# Draw Logo
|
||||
logoImg = utils.ImageReader( logoImageFile )
|
||||
logoSize = logoImg.getSize()
|
||||
logoFraction = 0.6
|
||||
logoSize = (logoFraction * logoSize[0], logoFraction*logoSize[1])
|
||||
logoPosition = ( ps[0] - 5*units.cm, titleAreaMidY - 0.5*logoSize[1] )
|
||||
canvas.drawImage( logoImg, logoPosition[0], logoPosition[1], width=logoSize[0], height=logoSize[1], mask=Color(0,0,0) )
|
||||
|
||||
# Draw Title
|
||||
text = canvas.beginText()
|
||||
text.setTextOrigin( 1 * units.cm, titleAreaMidY-25/2 )
|
||||
text.setFillColorRGB( 0.95,0.95,0.95 )
|
||||
text.setFont( 'Helvetica', 25 )
|
||||
text.textLine( "Inhaltsverzeichnis" )
|
||||
canvas.drawText( text )
|
||||
|
||||
# Draw Background
|
||||
bgImage = utils.ImageReader( bgImageFile )
|
||||
bgImageSize = bgImage.getSize()
|
||||
curPos = [0, gradientEnd[1]-bgImageSize[1] ]
|
||||
while curPos[1] > -bgImageSize[1]:
|
||||
curPos[0] = 0
|
||||
while curPos[0] < ps[0]:
|
||||
canvas.drawImage( bgImage, curPos[0], curPos[1] )
|
||||
curPos[0] += bgImageSize[0]
|
||||
|
||||
curPos[1] -= bgImageSize[1]
|
||||
|
||||
|
||||
class PdfImage(Flowable):
|
||||
"""PdfImage wraps the first page from a PDF file as a Flowable
|
||||
which can be included into a ReportLab Platypus document.
|
||||
Based on the vectorpdf extension in rst2pdf (http://code.google.com/p/rst2pdf/)"""
|
||||
|
||||
def __init__(self, filename_or_object, page=0, width=None, height=None, kind='direct'):
|
||||
from pdfrw import PdfReader
|
||||
from pdfrw.buildxobj import pagexobj
|
||||
|
||||
# If using StringIO buffer, set pointer to beginning
|
||||
if hasattr(filename_or_object, 'read'):
|
||||
filename_or_object.seek(0)
|
||||
page = PdfReader(filename_or_object, decompress=False).pages[page]
|
||||
self.xobj = pagexobj(page)
|
||||
self.imageWidth = width
|
||||
self.imageHeight = height
|
||||
x1, y1, x2, y2 = self.xobj.BBox
|
||||
|
||||
self._w, self._h = x2 - x1, y2 - y1
|
||||
if not self.imageWidth:
|
||||
self.imageWidth = self._w
|
||||
if not self.imageHeight:
|
||||
self.imageHeight = self._h
|
||||
self.__ratio = float(self.imageWidth)/self.imageHeight
|
||||
if kind in ['direct','absolute'] or width==None or height==None:
|
||||
self.drawWidth = width or self.imageWidth
|
||||
self.drawHeight = height or self.imageHeight
|
||||
elif kind in ['bound','proportional']:
|
||||
factor = min(float(width)/self._w,float(height)/self._h)
|
||||
self.drawWidth = self._w*factor
|
||||
self.drawHeight = self._h*factor
|
||||
|
||||
def wrap(self, aW, aH):
|
||||
return self.drawWidth, self.drawHeight
|
||||
|
||||
def drawOn(self, canv, x, y, _sW=0):
|
||||
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT
|
||||
from pdfrw.toreportlab import makerl
|
||||
|
||||
if _sW > 0 and hasattr(self, 'hAlign'):
|
||||
a = self.hAlign
|
||||
if a in ('CENTER', 'CENTRE', TA_CENTER):
|
||||
x += 0.5*_sW
|
||||
elif a in ('RIGHT', TA_RIGHT):
|
||||
x += _sW
|
||||
elif a not in ('LEFT', TA_LEFT):
|
||||
raise ValueError("Bad hAlign value " + str(a))
|
||||
|
||||
xobj = self.xobj
|
||||
xobj_name = makerl(canv._doc, xobj)
|
||||
|
||||
xscale = self.drawWidth/self._w
|
||||
yscale = self.drawHeight/self._h
|
||||
|
||||
x -= xobj.BBox[0] * xscale
|
||||
y -= xobj.BBox[1] * yscale
|
||||
|
||||
canv.saveState()
|
||||
canv.translate(x, y)
|
||||
canv.scale(xscale, yscale)
|
||||
canv.doForm(xobj_name)
|
||||
canv.restoreState()
|
||||
|
||||
|
||||
class Bookmark(Flowable):
|
||||
""" Utility class to display PDF bookmark. """
|
||||
def __init__(self, title, key):
|
||||
self.title = title
|
||||
self.key = key
|
||||
Flowable.__init__(self)
|
||||
|
||||
def wrap(self, availWidth, availHeight):
|
||||
""" Doesn't take up any space. """
|
||||
return (0, 0)
|
||||
|
||||
def draw(self):
|
||||
# set the bookmark outline to show when the file's opened
|
||||
self.canv.showOutline()
|
||||
# step 1: put a bookmark on the
|
||||
self.canv.bookmarkPage(self.key)
|
||||
# step 2: put an entry in the bookmark outline
|
||||
self.canv.addOutlineEntry(self.title, self.key, 0, 0)
|
||||
|
||||
|
||||
def repertoire_pdf( request ):
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename="Repertoire.pdf"'
|
||||
|
||||
# Create the PDF object, using the response object as its "file.
|
||||
doc = RepertoireDocTemplate(response, pagesize=pagesizes.A4)
|
||||
elements = []
|
||||
|
||||
elements.append( Bookmark("Inhaltsverzeichnis", "Contents") )
|
||||
#TOC
|
||||
data = []
|
||||
for piece in Piece.getRepertoire():
|
||||
data.append( [ "%d %s" % ( piece.repertoire_nr, piece.title ) ] )
|
||||
table = Table(data)
|
||||
table.hAlign = "LEFT"
|
||||
elements.append(table)
|
||||
|
||||
|
||||
elements.append( NextPageTemplate('FullPage') )
|
||||
elements.append(PageBreak())
|
||||
pagesize=pagesizes.A4
|
||||
for piece in Piece.getRepertoire():
|
||||
score = piece.get_score_for_user( request.user )
|
||||
filename = score.file
|
||||
bookmarkTitle = "%02d %s - %s " % ( piece.repertoire_nr, piece.title, score.score_type )
|
||||
elements.append( Bookmark( bookmarkTitle, str(piece.id) ) )
|
||||
|
||||
#TODO support also multiple pages!!
|
||||
image_flowable = PdfImage( filename, 0, width=pagesize[0]*0.98, height=pagesize[1] *0.98 )
|
||||
image_flowable.hAlign = "CENTER"
|
||||
elements.append( image_flowable )
|
||||
|
||||
|
||||
doc.build(elements)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
|
||||
def repertoire_toc( request ):
|
||||
response = HttpResponse(content_type='application/pdf')
|
||||
response['Content-Disposition'] = 'attachment; filename="Inhaltsverzeichnis.pdf"'
|
||||
|
||||
# Create the PDF object, using the response object as its "file.
|
||||
doc = RepertoireDocTemplate(response,pagesize=pagesizes.A4 )
|
||||
elements = []
|
||||
|
||||
data = []
|
||||
for piece in Piece.getRepertoire():
|
||||
data.append( [ "%d %s" % ( piece.repertoire_nr, piece.title ) ] )
|
||||
|
||||
table = Table(data)
|
||||
table.hAlign = "LEFT"
|
||||
elements.append(table)
|
||||
|
||||
doc.build(elements)
|
||||
|
||||
return response
|
||||
|
||||
Reference in New Issue
Block a user