blechreiz-website/scoremanager/pdf_views.py

222 lines
7.9 KiB
Python
Raw Normal View History

2014-02-15 18:07:00 +01:00
# ----------------------------- 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