222 lines
7.9 KiB
Python
222 lines
7.9 KiB
Python
|
# ----------------------------- 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
|
||
|
|