source: indico/indico/MaKaC/PDFinterface/conference.py @ 0c8aad

burotelhello-world-walkthroughipv6new-webexprov-dual-interfacev0.97-seriesv0.98-seriesv0.98.2v0.98.3v0.98b1v0.98b2v0.99v1.0v1.1
Last change on this file since 0c8aad was 0c8aad, checked in by Pedro Ferreira <jose.pedro.ferreira@…>, 4 years ago

Merge branch 'v0.97-series'

  • Timetable management, etc;

Conflicts:

indico/MaKaC/conference.py
indico/MaKaC/webinterface/pages/conferences.py
indico/MaKaC/webinterface/rh/base.py
indico/MaKaC/webinterface/rh/conferenceModif.py
indico/htdocs/css/Default.css
indico/htdocs/js/indico/Core/Effects.js
indico/htdocs/js/indico/Management/RoomBooking.js

  • Property mode set to 100644
File size: 134.6 KB
Line 
1# -*- coding: utf-8 -*-
2##
3## $Id: conference.py,v 1.60 2009/06/03 16:33:15 jose Exp $
4##
5## This file is part of CDS Indico.
6## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
7##
8## CDS Indico is free software; you can redistribute it and/or
9## modify it under the terms of the GNU General Public License as
10## published by the Free Software Foundation; either version 2 of the
11## License, or (at your option) any later version.
12##
13## CDS Indico is distributed in the hope that it will be useful, but
14## WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16## General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
20## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21
22import string
23import types
24from copy import deepcopy
25from textwrap import wrap, fill
26try :
27    from PIL import Image
28    HAVE_PIL = True
29except ImportError, e:
30    from MaKaC.PDFinterface.base import Image
31    HAVE_PIL = False
32from MaKaC.PDFinterface.base import escape
33from datetime import timedelta,datetime
34from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
35from reportlab.lib.units import inch, cm
36from reportlab.lib import colors
37from reportlab.lib.enums import TA_JUSTIFY, TA_CENTER, TA_LEFT, TA_RIGHT
38from reportlab.rl_config import defaultPageSize
39from reportlab.platypus import Table,TableStyle,KeepTogether, XPreformatted
40from reportlab.pdfgen import canvas
41#from PIL import Image
42from MaKaC.common.timezoneUtils import DisplayTZ,nowutc
43import MaKaC.webinterface.urlHandlers as urlHandlers
44import MaKaC.review as review
45import MaKaC.conference as conference
46import MaKaC.schedule as schedule
47from MaKaC.badge import BadgeTemplateItem
48from MaKaC.poster import PosterTemplateItem
49from MaKaC.registration import Registrant
50from MaKaC.PDFinterface.base import PDFBase, PDFWithTOC, Paragraph, Spacer, PageBreak, Preformatted, FileDummy, setTTFonts, PDFSizes, modifiedFontSize
51from MaKaC.webinterface.pages.tracks import AbstractStatusTrackViewFactory, _ASTrackViewPFOT, _ASTrackViewPA, _ASTrackViewDuplicated, _ASTrackViewMerged,_ASTrackViewAccepted
52from MaKaC.webinterface.common.abstractStatusWrapper import AbstractStatusList
53import MaKaC.common.filters as filters
54import MaKaC.webinterface.common.contribFilters as contribFilters
55from MaKaC.webinterface.common.contribStatusWrapper import ContribStatusList
56from MaKaC.errors import MaKaCError, NoReportError
57from MaKaC.webinterface.common.countries import CountryHolder
58from reportlab.lib.pagesizes import landscape, A4
59from MaKaC.badgeDesignConf import BadgeDesignConfiguration
60from MaKaC.posterDesignConf import PosterDesignConfiguration
61from MaKaC.webinterface.common.tools import strip_ml_tags
62import re
63from MaKaC.i18n import _
64
65# PIL is the library used by reportlab to work with images.
66# If it isn't available, we must NOT put images in the PDF.
67# Then before add an image, we must check the HAVE_PIL global variable
68
69
70styles = getSampleStyleSheet()
71charRplace = [
72[u'\u2019', u"'"],
73[u'\u0153', u"oe"],
74[u'\u2026', u"..."],
75[u'\u2013', u"-"],
76[u'\u2018', u"'"]
77]
78
79
80
81class ProgrammeToPDF(PDFBase):
82
83    def __init__(self, conf, doc=None, story=None, tz=None):
84        self._conf = conf
85        if not tz:
86            self._tz = self._conf.getTimezone()
87        else:
88            self._tz = tz
89        PDFBase.__init__(self, doc, story)
90        self._title = _("Conference Scientific Programme")
91
92    def firstPage(self, c, doc):
93        c.saveState()
94        if HAVE_PIL:
95            logo = self._conf.getLogo()
96            imagePath = ""
97            if logo:
98                imagePath = logo.getFilePath()
99            if imagePath:
100                img = Image.open(imagePath)
101                width, heigth = img.size
102                c.drawInlineImage(imagePath, self._PAGE_WIDTH/2.0 - width/2, self._PAGE_HEIGHT - inch - heigth)
103        height=self._drawWrappedString(c, strip_ml_tags(self._conf.getTitle()))
104        c.setFont('Times-Bold', 15)
105        height-=2*cm
106        c.drawCentredString(self._PAGE_WIDTH/2.0, height, "%s - %s"%(self._conf.getAdjustedStartDate(self._tz).strftime("%A %d %B %Y"), self._conf.getAdjustedEndDate(self._tz).strftime("%A %d %B %Y")))
107        if self._conf.getLocation():
108            height-=1*cm
109            c.drawCentredString(self._PAGE_WIDTH/2.0, height, escape(self._conf.getLocation().getName()))
110        c.setFont('Times-Bold', 30)
111        height-=6*cm
112        c.drawCentredString(self._PAGE_WIDTH/2.0, height, self._title)
113        self._drawWrappedString(c, "%s / %s"%(strip_ml_tags(self._conf.getTitle()),self._title), width=inch, height=0.75*inch, font='Times-Roman', size=9, color=(0.5,0.5,0.5), align="left", maximumWidth=self._PAGE_WIDTH-3.5*inch, measurement=inch, lineSpacing=0.15)
114        c.drawRightString(self._PAGE_WIDTH - inch, 0.75 * inch, nowutc().strftime("%A %d %B %Y"))
115        c.restoreState()
116
117    def laterPages(self, c, doc):
118        c.saveState()
119        self._drawWrappedString(c, "%s / %s"%(escape(strip_ml_tags(self._conf.getTitle())),self._title), width=inch, height=self._PAGE_HEIGHT-0.75*inch, font='Times-Roman', size=9, color=(0.5,0.5,0.5), align="left", maximumWidth=self._PAGE_WIDTH-3.5*inch, measurement=inch, lineSpacing=0.15)
120        c.drawCentredString(self._PAGE_WIDTH/2.0, 0.75 * inch, "Page %d "%doc.page)
121        c.drawRightString(self._PAGE_WIDTH - inch, self._PAGE_HEIGHT - 0.75 * inch, nowutc().strftime("%A %d %B %Y"))
122        c.restoreState()
123
124    def getBody(self, story=None):
125        if not story:
126            story = self._story
127        style = styles["Normal"]
128        style.alignment = TA_JUSTIFY
129        for track in self._conf.getTrackList():
130
131            bogustext = track.getTitle()
132            p = Paragraph(bogustext, styles["Heading1"])
133            self._story.append(p)
134            bogustext = track.getDescription()
135            p = Paragraph(bogustext, style)
136            story.append(p)
137            story.append(Spacer(1, 0.4*inch))
138
139
140
141class AbstractToPDF(PDFBase):
142
143    def __init__(self, conf, abstract, doc=None, story=None, tz=None):
144        self._conf = conf
145        if not tz:
146            self._tz = self._conf.getTimezone()
147        else:
148            self._tz = tz
149        self._abstract = abstract
150        if not story:
151            story = [Spacer(inch, 5*cm)]
152        PDFBase.__init__(self, doc, story)
153        self._title = _("Abstract")
154        self._PAGE_HEIGHT = defaultPageSize[1]
155        self._PAGE_WIDTH = defaultPageSize[0]
156
157    def firstPage(self, c, doc):
158        c.saveState()
159        showLogo = False
160        c.setFont('Times-Bold', 30)
161        if HAVE_PIL:
162            logo = self._conf.getLogo()
163            imagePath = ""
164            if logo:
165                imagePath = logo.getFilePath()
166            if imagePath:
167                img = Image.open(imagePath)
168                showLogo = True
169                width, heigth = img.size
170                c.drawInlineImage(imagePath, self._PAGE_WIDTH/4.0 - width/2, self._PAGE_HEIGHT - inch - heigth)
171                c.drawCentredString( self._PAGE_WIDTH*3/4, self._PAGE_HEIGHT - inch - heigth/2, escape(self._conf.getTitle()))
172        if not showLogo:
173            self._drawWrappedString(c, escape(self._conf.getTitle()), height=self._PAGE_HEIGHT - 2*inch)
174
175        c.setFont('Times-Bold', 25)
176        #c.drawCentredString(self._PAGE_WIDTH/2, self._PAGE_HEIGHT - inch - 5*cm, self._abstract.getTitle())
177        c.setLineWidth(3)
178        c.setStrokeGray(0.7)
179        #c.line(inch, self._PAGE_HEIGHT - inch - 6*cm, self._PAGE_WIDTH - inch, self._PAGE_HEIGHT - inch - 6*cm)
180        #c.line(inch, inch , self._PAGE_WIDTH - inch, inch)
181        c.setFont('Times-Roman', 10)
182        #c.drawString(0.5*inch, 0.5*inch, Config.getInstance().getBaseURL())
183        c.restoreState()
184
185    def _getTrackText(self):
186        text = _("""<b> _("Track classification")</b> : """)
187        status=self._abstract.getCurrentStatus()
188        if isinstance(status,review.AbstractStatusAccepted):
189            if status.getTrack() is not None:
190                text="%s%s"%(text,escape(status.getTrack().getTitle()))
191        else:
192            listTrack= []
193            for track in self._abstract.getTrackListSorted():
194                listTrack.append( escape(track.getTitle()))
195            text += " ; ".join(listTrack)
196        return text
197
198    def _getContribTypeText(self):
199        status=self._abstract.getCurrentStatus()
200        if isinstance(status,review.AbstractStatusAccepted):
201            text= _("""<b> _("Contribution type")</b> : %s""")%(escape(str(status.getType())))
202        else:
203            text= _("""<b> _("Contribution type")</b> : %s""")%escape(str(self._abstract.getContribType()))
204        return text
205
206    def getBody(self, story=None, indexedFlowable={}, level=1 ):
207        if not story:
208            story = self._story
209
210        style = ParagraphStyle({})
211        style.fontSize = 12
212        text = _(""" _("Abstract ID") : %s""")%self._abstract.getId()
213        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
214        story.append(p)
215
216        story.append(Spacer(inch, 0.5*cm, part=escape(self._abstract.getTitle())))
217
218        style = ParagraphStyle({})
219        style.alignment = TA_CENTER
220        style.fontSize = 25
221        style.leading = 30
222        text = escape(self._abstract.getTitle())
223        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
224        story.append(p)
225
226        indexedFlowable[p] = {"text":escape(self._abstract.getTitle()), "level":1}
227
228        style = ParagraphStyle({})
229        style.fontName = "LinuxLibertine"
230        style.fontSize = 9
231        #XXX:Not optimal, but the only way I've found to do it
232        #l=self._abstract.getField("content").split("\n")
233        #res=[]
234        #for line in l:
235        #    res.append(fill(line,85))
236        #res="\n".join(res)
237        #p = Preformatted(escape(res), style, part=escape(self._abstract.getTitle()))
238        #story.append(p)
239
240        story.append(Spacer(inch, 0.5*cm, part=escape(self._abstract.getTitle())))
241
242        for field in self._conf.getAbstractMgr().getAbstractFieldsMgr().getActiveFields():
243            id = field.getId()
244            name = field.getName()
245            value = self._abstract.getField(id).strip()
246            if value: #id not in ["content"] and
247                styleHead = ParagraphStyle({})
248                styleHead.firstLineIndent = -45
249                styleHead.leftIndent = 45
250                text = "<b>%s</b> :" % name
251                p = Paragraph(text, styleHead, part=escape(self._abstract.getTitle()))
252                story.append(p)
253                l=value.split("\n")
254                res=[]
255                for line in l:
256                    res.append(fill(line,85))
257                res="\n".join(res)
258                p = Paragraph(escape(res), style, part=escape(self._abstract.getTitle()))
259                story.append(p)
260                story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
261
262        style = ParagraphStyle({})
263        style.firstLineIndent = -80
264        style.leftIndent = 80
265        text = _("""<b> _("Primary authors")</b> : """)
266        listAuthor = []
267        for author in self._abstract.getPrimaryAuthorsList():
268            listAuthor.append( "%s (%s)"%(escape(author.getFullName()), escape(author.getAffiliation()))  )
269        text += " ; ".join(listAuthor)
270        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
271        story.append(p)
272
273        story.append(Spacer(inch, 0.2*cm))
274
275        style = ParagraphStyle({})
276        style.firstLineIndent = -35
277        style.leftIndent = 35
278        text = _("""<b> _("Co-authors")</b> : """)
279        listAuthor = []
280        for author in self._abstract.getCoAuthorList():
281            listAuthor.append( "%s (%s)"%(escape(author.getFullName()), escape(author.getAffiliation()) )  )
282        text += " ; ".join(listAuthor)
283
284        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
285        story.append(p)
286
287        story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
288
289        style = ParagraphStyle({})
290        style.firstLineIndent = -45
291        style.leftIndent = 45
292        text = _("""<b> _("Presenter")</b> : """)
293        listSpeaker= []
294        for speaker in self._abstract.getSpeakerList():
295            listSpeaker.append( "%s (%s)"%(escape(speaker.getFullName()), escape(speaker.getAffiliation()) )  )
296        text += " ; ".join(listSpeaker)
297        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
298        story.append(p)
299
300        story.append(Spacer(inch, 0.5*cm, part=escape(self._abstract.getTitle())))
301        style = ParagraphStyle({})
302        style.firstLineIndent = -90
303        style.leftIndent = 90
304        p = Paragraph(self._getTrackText(), style, part=escape(self._abstract.getTitle()))
305        story.append(p)
306
307        story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
308        tmp= _("""--_("not specified")--""")
309        if self._abstract.getContribType() is not None:
310            tmp=self._abstract.getContribType().getName()
311        text = _("""<b> _("Contribution type")</b> : %s""")%escape(tmp)
312        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
313        story.append(p)
314
315        story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
316
317        text = _("""<b> _("Submitted by")</b> : %s""")%escape(self._abstract.getSubmitter().getFullName())
318        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
319        story.append(p)
320
321        story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
322
323        text = _("""<b> _("Submitted on")</b> %s""")%self._abstract.getSubmissionDate().strftime("%A %d %B %Y")
324        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
325        story.append(p)
326
327        story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
328
329        text = _("""<b> _("Last modified on")</b> : %s""")%self._abstract.getModificationDate().strftime("%A %d %B %Y")
330        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
331        story.append(p)
332
333        story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
334
335        text = _("""<b> _("Comments")</b> : """)
336        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
337        story.append(p)
338
339        style = ParagraphStyle({})
340        style.leftIndent = 40
341        text = "%s"%escape(self._abstract.getComments())
342        p = Preformatted(text, style, part=escape(self._abstract.getTitle()))
343        story.append(p)
344
345        return story
346
347
348class AbstractsToPDF(PDFWithTOC):
349
350    def __init__(self, conf, abstractList, tz=None):
351        self._conf = conf
352        if not tz:
353            self._tz = self._conf.getTimezone()
354        else:
355            self._tz = tz
356        self._abstracts = abstractList
357        self._title = _("Abstracts book")
358        PDFWithTOC.__init__(self)
359
360    def firstPage(self, c, doc):
361        c.saveState()
362        showLogo = False
363        c.setFont('Times-Bold', 30)
364        if HAVE_PIL:
365            logo = self._conf.getLogo()
366            imagePath = ""
367            if logo:
368                imagePath = logo.getFilePath()
369            if imagePath:
370                img = Image.open(imagePath)
371                showLogo = True
372                width, heigth = img.size
373                c.drawInlineImage(imagePath, self._PAGE_WIDTH/4.0 - width/2, self._PAGE_HEIGHT - inch - heigth)
374                c.drawCentredString( self._PAGE_WIDTH*3/4, self._PAGE_HEIGHT - inch - heigth/2, escape(self._conf.getTitle()))
375        if not showLogo:
376            self._drawWrappedString(c, escape(self._conf.getTitle()), height=self._PAGE_HEIGHT - 2*inch)
377
378        c.setFont('Times-Bold', 35)
379        c.drawCentredString(self._PAGE_WIDTH/2, self._PAGE_HEIGHT/2, self._title)
380        c.setLineWidth(3)
381        c.setStrokeGray(0.7)
382        c.setFont('Times-Roman', 10)
383        c.drawString(0.5*inch, 0.5*inch, str(urlHandlers.UHConferenceDisplay.getURL(self._conf)))
384        c.restoreState()
385
386    def laterPages(self, c, doc):
387
388        c.saveState()
389        c.setFont('Times-Roman', 9)
390        c.setFillColorRGB(0.5, 0.5, 0.5)
391        confTitle = escape(self._conf.getTitle())
392        if len(self._conf.getTitle())>30:
393            confTitle = escape(self._conf.getTitle()[:30] + "...")
394        c.drawString(inch, self._PAGE_HEIGHT - 0.75 * inch, "%s / %s"%(confTitle, self._title))
395        title = doc.getCurrentPart()
396        if len(doc.getCurrentPart())>50:
397            title = doc.getCurrentPart()[:50] + "..."
398        c.drawRightString(self._PAGE_WIDTH - inch, self._PAGE_HEIGHT - 0.75 * inch, "%s"%title)
399        c.drawRightString(self._PAGE_WIDTH - inch, 0.75 * inch, _(""" _("Page") %d """)%doc.page)
400        c.drawString(inch,  0.75 * inch, nowutc().strftime("%A %d %B %Y"))
401        c.restoreState()
402
403
404    def getBody(self):
405        for abstract in self._abstracts:
406            temp = AbstractToPDF(self._conf, abstract, tz=self._tz)
407            temp.getBody(self._story, indexedFlowable=self._indexedFlowable, level=1)
408            self._story.append(PageBreak())
409
410
411class ConfManagerAbstractToPDF(AbstractToPDF):
412
413    def _getTrackText(self):
414        text = _("""<b> _("Track classification")</b> : """)
415        listTrack= []
416        for track in self._abstract.getTrackListSorted():
417            listTrack.append( escape(track.getTitle()))
418        text += " ; ".join(listTrack)
419        return text
420
421    def _getContribTypeText(self):
422        status=self._abstract.getCurrentStatus()
423        text= _("""<b> _("Contribution type")</b> : %s""")%escape(str(self._abstract.getContribType()))
424        return text
425
426    def getBody(self, story=None, indexedFlowable={}, level=1 ):
427        if not story:
428            story = self._story
429        #get the common abstract content from parent
430        AbstractToPDF.getBody(self, story, indexedFlowable, level )
431        #add info for the conference manager
432        story.append(Spacer(inch, 0.5*cm, part=escape(self._abstract.getTitle())))
433        status = self._abstract.getCurrentStatus()
434        style = ParagraphStyle({})
435        style.firstLineIndent = -90
436        style.leftIndent = 90
437        if status.__class__ == review.AbstractStatusDuplicated:
438            original=status.getOriginal()
439            st = _(""" _("DUPLICATED") (%s : %s)""")%(original.getId(), original.getTitle())
440        elif status.__class__ == review.AbstractStatusMerged:
441            target=status.getTargetAbstract()
442            st = _(""" _("MERGED") (%s : %s)""")%(target.getId(), target.getTitle())
443        else:
444            st = AbstractStatusList().getCaption( status.__class__ ).upper()
445        text = _("""<b> _("Status")</b> : %s""")%escape(st)
446        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
447        story.append(p)
448        story.append(Spacer(inch, 0.5*cm, part=escape(self._abstract.getTitle())))
449        style = ParagraphStyle({})
450        style.firstLineIndent = -90
451        style.leftIndent = 90
452        text = _("""<b> _("Track judgments")</b> :""")
453        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
454        story.append(p)
455
456        for track in self._abstract.getTrackListSorted():
457            status = self._abstract.getTrackJudgement(track)
458            if status.__class__ == review.AbstractAcceptance:
459                contribType = ""
460                if status.getContribType() is not None:
461                    contribType = "(%s)"%status.getContribType().getName()
462                st = _(""" _("Proposed to accept") %s""")%(contribType)
463                modifDate = status.getDate().strftime("%d %B %Y %H:%M")
464                modifier = status.getResponsible().getFullName()
465                comments = escape(status.getComment())
466            elif status.__class__ == review.AbstractRejection:
467                st = _("Proposed to reject")
468                modifDate = status.getDate().strftime("%d %B %Y %H:%M")
469                modifier = status.getResponsible().getFullName()
470                comments = escape(status.getComment())
471            elif status.__class__ == review.AbstractReallocation:
472                l = []
473                for track in status.getProposedTrackList():
474                    l.append( track.getTitle() )
475                st = _(""" _("Proposed for other tracks") (%s)""")%", ".join(l)
476                modifDate = status.getDate().strftime("%d %B %Y %H:%M")
477                modifier = status.getResponsible().getFullName()
478                comments = escape(status.getComment())
479            else:
480                st = ""
481                modifDate = ""
482                modifier = ""
483                comments = ""
484
485            story.append(Spacer(inch, 0.5*cm, part=escape(self._abstract.getTitle())))
486
487            status = self._abstract.getCurrentStatus()
488            style = ParagraphStyle({})
489            style.firstLineIndent = -90
490            style.leftIndent = 130
491            text = _(""" _("Track") : %s""")%escape(track.getTitle())
492            p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
493            story.append(p)
494
495            story.append(Spacer(inch, 0.1*cm, part=escape(self._abstract.getTitle())))
496
497            status = self._abstract.getCurrentStatus()
498            style = ParagraphStyle({})
499            style.firstLineIndent = -90
500            style.leftIndent = 170
501            text = _(""" _("Judgment") : %s""")%st
502            p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
503            story.append(p)
504
505            #story.append(Spacer(inch, 0.1*cm, part=self._abstract.getTitle()))
506
507            status = self._abstract.getCurrentStatus()
508            style = ParagraphStyle({})
509            style.firstLineIndent = -90
510            style.leftIndent = 170
511            text = _(""" _("Judged by") : %s""")%modifier
512            p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
513            story.append(p)
514
515            #story.append(Spacer(inch, 0.1*cm, part=self._abstract.getTitle()))
516
517            status = self._abstract.getCurrentStatus()
518            style = ParagraphStyle({})
519            style.firstLineIndent = -90
520            style.leftIndent = 170
521            text = _(""" _("Date") : %s""")%modifDate
522            p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
523            story.append(p)
524
525            #story.append(Spacer(inch, 0.1*cm, part=self._abstract.getTitle()))
526
527            status = self._abstract.getCurrentStatus()
528            style = ParagraphStyle({})
529            style.firstLineIndent = -55
530            style.leftIndent = 135
531            text = _(""" _("Comments") : \"<i>%s</i>\"""")%comments
532            p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
533            story.append(p)
534
535
536class ConfManagerAbstractsToPDF(AbstractsToPDF):
537
538    def getBody(self):
539        for abstract in self._abstracts:
540            temp = ConfManagerAbstractToPDF(self._conf, abstract,tz=self._tz)
541            temp.getBody(self._story, indexedFlowable=self._indexedFlowable, level=1)
542            self._story.append(PageBreak())
543
544
545class TrackManagerAbstractToPDF(AbstractToPDF):
546
547    def __init__(self, conf, abstract, track, doc=None, story=None, tz=None):
548        AbstractToPDF.__init__(self, conf, abstract, doc, story, tz=tz)
549        self._track = track
550#        self._tz = tz
551
552    def _getTrackText(self):
553        text = _("""<b> _("Track classification")</b> : """)
554        listTrack= []
555        for track in self._abstract.getTrackListSorted():
556            listTrack.append( escape(track.getTitle()))
557        text += " ; ".join(listTrack)
558        return text
559
560    def _getContribTypeText(self):
561        status=self._abstract.getCurrentStatus()
562        text= _("""<b> _("Contribution type")</b> : %s""")%escape(str(self._abstract.getContribType()))
563        return text
564
565    def getBody(self, story=None, indexedFlowable={}, level=1 ):
566        if not story:
567            story = self._story
568        #get the common abstract content from parent
569        AbstractToPDF.getBody(self, story, indexedFlowable, level )
570
571        #add info for the track manager
572        status=AbstractStatusTrackViewFactory.getStatus(self._track,self._abstract)
573        comments = escape(status.getComment())
574        st = status.getLabel().upper()
575        conflictText, res = "", ""
576        if isinstance(status, _ASTrackViewPFOT):
577            l = []
578            for track in status.getProposedTrackList():
579                l.append( escape(track.getTitle()) )
580            res = "%s"%", ".join(l)
581        elif isinstance(status, _ASTrackViewPA):
582            contribType = ""
583            if status.getContribType() is not None:
584                contribType = "(%s)"%status.getContribType().getName()
585            res = "%s %s"%( status.getLabel().upper(), \
586                              contribType )
587            conflicts = status.getConflicts()
588            if conflicts:
589                l = []
590                for jud in conflicts:
591                    if jud.getTrack() != self._track:
592                        l.append( "%s ( %s )"%( jud.getTrack().getTitle(), \
593                                escape(jud.getResponsible().getFullName()) ) )
594                conflictText = ",\n".join(l)
595        elif isinstance(status, _ASTrackViewDuplicated):
596            orig = status.getOriginal()
597            st =  "%s (%s : %s)"%(status.getLabel().upper(), orig.getId(), orig.getTitle())
598        elif isinstance(status, _ASTrackViewMerged):
599            target=status.getTarget()
600            st = "%s (%s : %s)"%(status.getLabel().upper(), target.getId(), target.getTitle())
601        elif isinstance(status,_ASTrackViewAccepted):
602            if status.getContribType() is not None and \
603                                                status.getContribType()!="":
604                contribType = ""
605                if status.getContribType() is not None:
606                    contribType = "(%s)"%status.getContribType().getName()
607                st = "%s %s"%(status.getLabel().upper(),contribType)
608        modifier = ""
609        if status.getResponsible():
610            modifier = escape(status.getResponsible().getFullName())
611        modifDate = ""
612        if status.getDate():
613            modifDate = status.getDate().strftime( "%d %B %Y %H:%M" )
614        story.append(Spacer(inch, 0.5*cm, part=escape(self._abstract.getTitle())))
615        status = self._abstract.getCurrentStatus()
616        style = ParagraphStyle({})
617        style.firstLineIndent = -90
618        style.leftIndent = 90
619        if st:
620            text = _("""<b> _("Status")</b> : %s""")%st
621            if modifier or modifDate:
622                text += " (%s)"%" - ".join( [modifier, modifDate])
623
624        else:
625            text = _("""<b> _("Status")</b> : _("SUBMITTED")""")
626        p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
627        story.append(p)
628
629
630
631        #story.append(Spacer(inch, 0.1*cm, part=self._abstract.getTitle()))
632
633        if res:
634            status = self._abstract.getCurrentStatus()
635            style = ParagraphStyle({})
636            style.leftIndent = 60
637            text = "(<i>%s</i>)"%res
638            p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
639            story.append(p)
640
641
642        if comments:
643            status = self._abstract.getCurrentStatus()
644            style = ParagraphStyle({})
645            style.leftIndent = 40
646            text = "\"<i>%s</i>\""%comments
647            p = Paragraph(text, style, part=escape(self._abstract.getTitle()))
648            story.append(p)
649
650        story.append(Spacer(inch, 0.2*cm, part=escape(self._abstract.getTitle())))
651
652        if conflictText:
653            style = ParagraphStyle({})
654            style.leftIndent = 40
655            p = Paragraph( _(""" _("In conflict with"): """), style, part=escape(self._abstract.getTitle()))
656            story.append(p)
657
658            style = ParagraphStyle({})
659            style.leftIndent = 60
660            p = Preformatted(conflictText, style, part=escape(self._abstract.getTitle()))
661            story.append(p)
662
663
664class TrackManagerAbstractsToPDF(AbstractsToPDF):
665
666    def __init__(self, conf, track, abstractList, tz=None):
667        AbstractsToPDF.__init__(self, conf, abstractList, tz)
668        self._track = track
669
670    def getBody(self):
671        for abstract in self._abstracts:
672            temp = TrackManagerAbstractToPDF(self._conf, abstract, self._track, tz=self._tz)
673            temp.getBody(self._story, indexedFlowable=self._indexedFlowable, level=1)
674            self._story.append(PageBreak())
675
676
677class ContribToPDF(PDFBase):
678
679    def __init__(self, conf, contrib, doc=None, story=None, tz=None):
680        self._conf = conf
681        if not tz:
682            self._tz = self._conf.getTimezone()
683        else:
684            self._tz = tz
685        self._contrib = contrib
686        if not story:
687            story = [Spacer(inch, 5*cm)]
688        PDFBase.__init__(self, doc, story)
689        self._title = _("Contribution")
690        self._PAGE_HEIGHT = defaultPageSize[1]
691        self._PAGE_WIDTH = defaultPageSize[0]
692
693    def firstPage(self, c, doc):
694        c.saveState()
695        showLogo = False
696        c.setFont('Times-Bold', 30)
697        if HAVE_PIL:
698            logo = self._conf.getLogo()
699            imagePath = ""
700            if logo:
701                imagePath = logo.getFilePath()
702            if imagePath:
703                img = Image.open(imagePath)
704                showLogo = True
705                width, heigth = img.size
706                c.drawInlineImage(imagePath, self._PAGE_WIDTH/4.0 - width/2, self._PAGE_HEIGHT - inch - heigth)
707                c.drawCentredString( self._PAGE_WIDTH*3/4, self._PAGE_HEIGHT - inch - heigth/2, escape(self._conf.getTitle()))
708        if not showLogo:
709            self._drawWrappedString(c, escape(self._conf.getTitle()), height=self._PAGE_HEIGHT - 2*inch)
710        c.setFont('Times-Bold', 25)
711        #c.drawCentredString(self._PAGE_WIDTH/2, self._PAGE_HEIGHT - inch - 5*cm, self._abstract.getTitle())
712        c.setLineWidth(3)
713        c.setStrokeGray(0.7)
714        #c.line(inch, self._PAGE_HEIGHT - inch - 6*cm, self._PAGE_WIDTH - inch, self._PAGE_HEIGHT - inch - 6*cm)
715        #c.line(inch, inch , self._PAGE_WIDTH - inch, inch)
716        c.setFont('Times-Roman', 10)
717        #c.drawString(0.5*inch, 0.5*inch, Config.getInstance().getBaseURL())
718        c.restoreState()
719
720    def getBody(self, story=None, indexedFlowable={}, level=1 ):
721        if not story:
722            story = self._story
723
724        style = ParagraphStyle({})
725        style.fontSize = 12
726        text = _(""" _("Contribution ID") : %s""")%self._contrib.getId()
727        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
728        story.append(p)
729
730        story.append(Spacer(inch, 0.5*cm, part=escape(self._contrib.getTitle())))
731
732        style = ParagraphStyle({})
733        style.alignment = TA_CENTER
734        style.fontSize = 25
735        style.leading = 30
736        text = escape(self._contrib.getTitle())
737        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
738        story.append(p)
739
740        if self._contrib.isScheduled():
741            style = ParagraphStyle({})
742            style.alignment = TA_CENTER
743            style.fontSize = 12
744            style.leading = 30
745            text = "%s (%s)" % (escape(self._contrib.getAdjustedStartDate(self._tz).strftime("%A %d %b %Y at %H:%M")),escape((datetime(1900,1,1)+self._contrib.getDuration()).strftime("%Hh%M'")))
746            p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
747            story.append(p)
748
749        indexedFlowable[p] = {"text":escape(self._contrib.getTitle()), "level":1}
750
751        story.append(Spacer(inch, 1*cm, part=escape(self._contrib.getTitle())))
752
753        style = ParagraphStyle({})
754        style.fontName = "LinuxLibertine"
755        style.fontSize = 9
756        #p = Paragraph(escape(self._contrib.getDescription()), style, part=escape(self._contrib.getTitle()))
757        #story.append(p)
758
759        #story.append(Spacer(inch, 0.2*cm, part=escape(self._contrib.getTitle())))
760
761        for field in self._conf.getAbstractMgr().getAbstractFieldsMgr().getActiveFields():
762            fid = field.getId()
763            name = field.getName()
764            value = self._contrib.getField(fid).strip()
765            if value: #id not in ["content"] and
766                styleHead = ParagraphStyle({})
767                styleHead.firstLineIndent = -55
768                styleHead.leftIndent = 45
769                text = "<b>%s</b> :" % name
770                p = Paragraph(text, styleHead, part=escape(self._contrib.getTitle()))
771                story.append(p)
772                l=value.split("\n")
773                res=[]
774                for line in l:
775                    res.append(fill(line,85))
776                res="\n".join(res)
777                p = Paragraph(escape(res), style, part=escape(self._contrib.getTitle()))
778                story.append(p)
779                story.append(Spacer(inch, 0.2*cm, part=escape(self._contrib.getTitle())))
780
781        story.append(Spacer(inch, 0.5*cm, part=escape(self._contrib.getTitle())))
782
783        style = ParagraphStyle({})
784        style.firstLineIndent = -80
785        style.leftIndent = 80
786        text = _("""<b> _("Primary authors")</b> : """)
787        listAuthor = []
788        for author in self._contrib.getPrimaryAuthorsList():
789            listAuthor.append( "%s (%s)"%(escape(author.getFullName()), escape(author.getAffiliation()))  )
790        text += " ; ".join(listAuthor)
791        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
792        story.append(p)
793
794        story.append(Spacer(inch, 0.2*cm))
795
796        style = ParagraphStyle({})
797        style.firstLineIndent = -35
798        style.leftIndent = 35
799        text = _("""<b> _("Co-authors")</b> : """)
800        listAuthor = []
801        for author in self._contrib.getCoAuthorList():
802            listAuthor.append( "%s (%s)"%(escape(author.getFullName()), escape(author.getAffiliation()) )  )
803        text += " ; ".join(listAuthor)
804
805        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
806        story.append(p)
807
808        story.append(Spacer(inch, 0.2*cm, part=escape(self._contrib.getTitle())))
809
810        style = ParagraphStyle({})
811        style.firstLineIndent = -45
812        style.leftIndent = 45
813        text = _("""<b> _("Presenter")</b> : """)
814        listSpeaker= []
815        for speaker in self._contrib.getSpeakerList():
816            listSpeaker.append( "%s (%s)"%(escape(speaker.getFullName()), escape(speaker.getAffiliation()) )  )
817        text += " ; ".join(listSpeaker)
818        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
819        story.append(p)
820
821        story.append(Spacer(inch, 0.5*cm, part=escape(self._contrib.getTitle())))
822        style = ParagraphStyle({})
823        style.firstLineIndent = -90
824        style.leftIndent = 90
825        session = self._contrib.getSession()
826        if session!=None:
827            sessiontitle = session.getTitle()
828        else:
829            sessiontitle = _("""--_("not yet classified")--""")
830        text = _("""<b> _("Session classification") </b> :  %s""")%escape(sessiontitle)
831        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
832        story.append(p)
833
834        story.append(Spacer(inch, 0.5*cm, part=escape(self._contrib.getTitle())))
835
836        style = ParagraphStyle({})
837        style.firstLineIndent = -90
838        style.leftIndent = 90
839        track = self._contrib.getTrack()
840        if track!=None:
841            tracktitle = track.getTitle()
842        else:
843            tracktitle = _("""--_("not yet classified")--""")
844        text = _("""<b> _("Track classification")</b> :  %s""")%escape(tracktitle)
845        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
846        story.append(p)
847
848        story.append(Spacer(inch, 0.2*cm, part=escape(self._contrib.getTitle())))
849
850        tmp=_("""--_("not specified")--""")
851        if self._contrib.getType():
852            tmp=self._contrib.getType().getName()
853        text = _("""<b> _("Type")</b> : %s""")%escape(tmp)
854        p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
855        story.append(p)
856
857        # TB: Do we really need to display the submitssion info of a contribution?
858        #story.append(Spacer(inch, 0.2*cm, part=escape(self._contrib.getTitle())))
859
860        #text = "<b>Submitted by</b> : %s"%escape(self._contrib.getSubmitter().getFullName())
861        #p = Paragraph(text, style, part=escape(self._contrib.getTitle()))
862        #story.append(p)
863
864        return story
865
866class ConfManagerContribToPDF(ContribToPDF):
867
868    def getBody(self, story=None, indexedFlowable={}, level=1 ):
869        if not story:
870            story = self._story
871
872        #get the common contribution content from parent
873        ContribToPDF.getBody(self, story, indexedFlowable, level )
874
875        #add info for the conference manager
876
877
878class ContributionBook(PDFBase):
879
880    def __init__(self,conf,contribList,aw,tz=None):
881        self._conf=conf
882        if not tz:
883            self._tz = self._conf.getTimezone()
884        else:
885            self._tz = tz
886        self._contribList = contribList
887        self._aw=aw
888        PDFBase.__init__(self)
889        self._title=_("Book of abstracts")
890        self._doc.leftMargin=1*cm
891        self._doc.rightMargin=1*cm
892        self._doc.topMargin=1.5*cm
893        self._doc.bottomMargin=1*cm
894
895    def firstPage(self,c,doc):
896        c.saveState()
897        if HAVE_PIL:
898            logo=self._conf.getLogo()
899            imagePath=""
900            if logo:
901                imagePath=logo.getFilePath()
902            if imagePath:
903                img=Image.open(imagePath)
904                width,heigth=img.size
905                c.drawInlineImage(imagePath,self._PAGE_WIDTH/2.0-width/2,
906                    self._PAGE_HEIGHT-inch-heigth)
907        height=self._drawWrappedString(c, self._conf.getTitle())
908        c.setFont('Times-Bold',15)
909        height-=2*cm
910        c.drawCentredString(self._PAGE_WIDTH/2.0,height,
911                "%s - %s"%(self._conf.getAdjustedStartDate(self._tz).strftime("%A %d %B %Y"),
912                self._conf.getAdjustedEndDate(self._tz).strftime("%A %d %B %Y")))
913        if self._conf.getLocation():
914            height-=1*cm
915            c.drawCentredString(self._PAGE_WIDTH/2.0,height,
916                    escape(self._conf.getLocation().getName()))
917        c.setFont('Times-Bold', 30)
918        height-=6*cm
919        c.drawCentredString(self._PAGE_WIDTH/2.0,height,\
920                self._title)
921        self._drawWrappedString(c, "%s / %s"%(self._conf.getTitle(),self._title), width=inch, height=0.75*inch, font='Times-Roman', size=9, color=(0.5,0.5,0.5), align="left", maximumWidth=self._PAGE_WIDTH-3.5*inch, measurement=inch, lineSpacing=0.15)
922        c.drawRightString(self._PAGE_WIDTH-inch,0.75*inch,
923                nowutc().strftime("%A %d %B %Y"))
924        c.restoreState()
925
926    def laterPages(self,c,doc):
927        c.saveState()
928        c.setFont('Times-Roman',9)
929        c.setFillColorRGB(0.5,0.5,0.5)
930        c.drawString(1*cm,self._PAGE_HEIGHT-1*cm,
931            "%s / %s"%(escape(self._conf.getTitle()),self._title))
932        c.drawCentredString(self._PAGE_WIDTH/2.0,0.5*cm,"Page %d "%doc.page)
933        c.restoreState()
934
935    def _defineStyles(self):
936        self._styles={}
937        titleStyle=getSampleStyleSheet()["Heading1"]
938        titleStyle.fontSize=13.0
939        titleStyle.spaceBefore=0
940        titleStyle.spaceAfter=4
941        titleStyle.leading=14
942        self._styles["title"]=titleStyle
943        spkStyle=getSampleStyleSheet()["Heading2"]
944        spkStyle.fontSize=10.0
945        spkStyle.spaceBefore=0
946        spkStyle.spaceAfter=0
947        spkStyle.leading=14
948        self._styles["speakers"]=spkStyle
949        abstractStyle=getSampleStyleSheet()["Normal"]
950        abstractStyle.fontSize=10.0
951        abstractStyle.spaceBefore=0
952        abstractStyle.spaceAfter=0
953        abstractStyle.alignment=TA_LEFT
954        self._styles["abstract"]=abstractStyle
955        ttInfoStyle=getSampleStyleSheet()["Normal"]
956        ttInfoStyle.fontSize=10.0
957        ttInfoStyle.spaceBefore=0
958        ttInfoStyle.spaceAfter=0
959        self._styles["tt_info"]=ttInfoStyle
960        normalStyle=getSampleStyleSheet()["Normal"]
961        normalStyle.fontSize=10.0
962        normalStyle.spaceBefore=5
963        normalStyle.spaceAfter=5
964        normalStyle.alignment=TA_LEFT
965        self._styles["normal"]=normalStyle
966
967    def getBody(self,story=None):
968        self._defineStyles()
969        if not story:
970            story=self._story
971        story.append(PageBreak())
972        if self._conf.getBOAConfig().getText() != "":
973            text=self._conf.getBOAConfig().getText().replace("<BR>","<br>")
974            text=text.replace("<Br>","<br>")
975            text=text.replace("<bR>","<br>")
976            for par in text.split("<br>"):
977                p=Paragraph(par,self._styles["normal"])
978                story.append(p)
979            story.append(PageBreak())
980        for contrib in self._contribList:
981            if not contrib.canAccess(self._aw):
982                continue
983            caption="%s - %s"%(contrib.getId(),contrib.getTitle())
984            p1=Paragraph(escape(caption),self._styles["title"])
985            lspk=[]
986            for spk in contrib.getSpeakerList():
987                fullName=spk.getFullName()
988                instit=spk.getAffiliation().strip()
989                if instit!="":
990                    fullName="%s (%s)"%(fullName, instit)
991                lspk.append("%s"%escape(fullName))
992            speakers= _("""<b> _("Presenter"): %s</b>""")%"; ".join(lspk)
993            p2=Paragraph(speakers,self._styles["speakers"])
994            abstract=contrib.getDescription()
995            p3=Paragraph(escape(abstract),self._styles["abstract"])
996            if contrib.isScheduled():
997                ses=""
998                if contrib.getSession() is not None:
999                    ses="%s - "%contrib.getSession().getTitle()
1000                text="%s%s"%(ses,contrib.getAdjustedStartDate(self._tz).strftime("%A %d %B %Y %H:%M"))
1001                p4=Paragraph(escape(text),self._styles["tt_info"])
1002                abs=KeepTogether([p1,p4,p2,p3])
1003            else:
1004                abs=KeepTogether([p1,p2,p3])
1005            story.append(abs)
1006            story.append(Spacer(1,0.4*inch))
1007
1008
1009class ContribsToPDF(PDFWithTOC):
1010
1011    def __init__(self, conf, contribList, tz=None):
1012        self._conf = conf
1013        if not tz:
1014            self._tz = self._conf.getTimezone()
1015        else:
1016            self._tz = tz
1017        self._contribs = contribList
1018        self._title = _("Contributions book")
1019        PDFWithTOC.__init__(self)
1020
1021    def firstPage(self, c, doc):
1022        c.saveState()
1023        showLogo = False
1024        c.setFont('Times-Bold', 30)
1025        if HAVE_PIL:
1026            logo = self._conf.getLogo()
1027            imagePath = ""
1028            if logo:
1029                imagePath = logo.getFilePath()
1030            if imagePath:
1031                img = Image.open(imagePath)
1032                showLogo = True
1033                width, heigth = img.size
1034                c.drawInlineImage(imagePath, self._PAGE_WIDTH/4.0 - width/2, self._PAGE_HEIGHT - inch - heigth)
1035                c.drawCentredString( self._PAGE_WIDTH*3/4, self._PAGE_HEIGHT - inch - heigth/2, escape(self._conf.getTitle()))
1036        if not showLogo:
1037            self._drawWrappedString(c, escape(self._conf.getTitle()), height=self._PAGE_HEIGHT - 2*inch)
1038        c.setFont('Times-Bold', 35)
1039        c.drawCentredString(self._PAGE_WIDTH/2, self._PAGE_HEIGHT/2, self._title)
1040        c.setLineWidth(3)
1041        c.setStrokeGray(0.7)
1042        #c.line(inch, self._PAGE_HEIGHT - inch - 6*cm, self._PAGE_WIDTH - inch, self._PAGE_HEIGHT - inch - 6*cm)
1043        #c.line(inch, inch , self._PAGE_WIDTH - inch, inch)
1044        c.setFont('Times-Roman', 10)
1045        c.drawString(0.5*inch, 0.5*inch, str(urlHandlers.UHConferenceDisplay.getURL(self._conf)))
1046        c.restoreState()
1047
1048    def laterPages(self, c, doc):
1049
1050        c.saveState()
1051        c.setFont('Times-Roman', 9)
1052        c.setFillColorRGB(0.5, 0.5, 0.5)
1053        confTitle = escape(self._conf.getTitle())
1054        if len(self._conf.getTitle())>30:
1055            confTitle = escape(self._conf.getTitle()[:30] + "...")
1056        c.drawString(inch, self._PAGE_HEIGHT - 0.75 * inch, "%s / %s"%(confTitle, self._title))
1057        title = doc.getCurrentPart()
1058        if len(doc.getCurrentPart())>50:
1059            title = doc.getCurrentPart()[:50] + "..."
1060        c.drawRightString(self._PAGE_WIDTH - inch, self._PAGE_HEIGHT - 0.75 * inch, "%s"%title)
1061        c.drawRightString(self._PAGE_WIDTH - inch, 0.75 * inch, _(""" _("Page") %d """)%doc.page)
1062        c.drawString(inch,  0.75 * inch, nowutc().strftime("%A %d %B %Y"))
1063        c.restoreState()
1064
1065
1066    def getBody(self):
1067        for contrib in self._contribs:
1068            temp = ContribToPDF(self._conf, contrib, tz=self._tz)
1069            temp.getBody(self._story, indexedFlowable=self._indexedFlowable, level=1)
1070            self._story.append(PageBreak())
1071
1072class ConfManagerContribsToPDF(ContribsToPDF):
1073
1074    def getBody(self):
1075        for contrib in self._contribs:
1076            temp = ConfManagerContribToPDF(self._conf, contrib,tz=self._tz)
1077            temp.getBody(self._story, indexedFlowable=self._indexedFlowable, level=1)
1078            self._story.append(PageBreak())
1079
1080class TimetablePDFFormat:
1081
1082    def __init__(self, params=None):
1083        if params is None:
1084            self.contribId = True
1085            self.speakerTitle = True
1086            self.contribAbstract = False
1087            self.newPagePerSession = False
1088            self.useSessionColorCodes = False
1089            self.showSessionTOC = False
1090            self.logo = False
1091            self.lengthContribs = False
1092            self.contribsAtConfLevel=False
1093            self.breaksAtConfLevel=False
1094            self.dateCloseToSessions=False
1095            self.coverPage=True
1096            self.tableContents=True
1097        else:
1098            self.setValues(params)
1099
1100    def setValues(self, params):
1101        self.contribId = True
1102        if not params.has_key("showContribId"):
1103            self.contribId = False
1104
1105        self.speakerTitle = True
1106        if not params.has_key("showSpeakerTitle"):
1107            self.speakerTitle = False
1108
1109        self.contribAbstract = False
1110        if params.has_key("showAbstract"):
1111            self.contribAbstract = True
1112
1113        self.contribPosterAbstract = True
1114        if params.has_key("dontShowPosterAbstract"):
1115            self.contribPosterAbstract = False
1116
1117        self.newPagePerSession = False
1118        if params.has_key("newPagePerSession"):
1119            self.newPagePerSession = True
1120
1121        self.useSessionColorCodes = False
1122        if params.has_key("useSessionColorCodes"):
1123            self.useSessionColorCodes = True
1124
1125        self.showSessionTOC = False
1126        if params.has_key("showSessionTOC"):
1127            self.showSessionTOC = True
1128
1129        self.lengthContribs = False
1130        if params.has_key("showLengthContribs"):
1131            self.lengthContribs = True
1132
1133        self.contribsAtConfLevel = False
1134        if params.has_key("showContribsAtConfLevel"):
1135            self.contribsAtConfLevel = True
1136
1137        self.breaksAtConfLevel = False
1138        if params.has_key("showBreaksAtConfLevel"):
1139            self.breaksAtConfLevel = True
1140
1141        self.dateCloseToSessions = False
1142        if params.has_key("printDateCloseToSessions"):
1143            self.dateCloseToSessions = True
1144
1145        self.coverPage=True
1146        if not params.has_key("showCoverPage"):
1147            self.coverPage = False
1148
1149        self.tableContents=True
1150        if not params.has_key("showTableContents"):
1151            self.tableContents = False
1152
1153        self.logo = False
1154
1155    def showContribId(self):
1156        return self.contribId
1157
1158    def showSpeakerTitle(self):
1159        return self.speakerTitle
1160
1161    def showContribAbstract(self):
1162        return self.contribAbstract
1163
1164    def showContribPosterAbstract(self):
1165        return self.contribPosterAbstract
1166
1167    def showLogo(self):
1168        return self.logo
1169
1170    def showNewPagePerSession(self):
1171        return self.newPagePerSession
1172
1173    def showUseSessionColorCodes(self):
1174        return self.useSessionColorCodes
1175
1176    def showTitleSessionTOC(self):
1177        return self.showSessionTOC
1178
1179    def showLengthContribs(self):
1180        return self.lengthContribs
1181
1182    def showContribsAtConfLevel(self):
1183        return self.contribsAtConfLevel
1184
1185    def showBreaksAtConfLevel(self):
1186        return self.breaksAtConfLevel
1187
1188    def showDateCloseToSessions(self):
1189        return self.dateCloseToSessions
1190
1191    def showCoverPage(self):
1192        return self.coverPage
1193
1194    def showTableContents(self):
1195        return self.tableContents
1196
1197
1198def sortEntries(x,y):
1199    if cmp(x.getStartDate(),y.getStartDate()):
1200        return cmp(x.getStartDate(),y.getStartDate())
1201    else:
1202        try:
1203            return cmp(x.getOwner().getSession().getTitle(),y.getOwner().getSession().getTitle())
1204        except:
1205            return cmp(x.getTitle(),y.getTitle())
1206
1207class TimeTablePlain(PDFWithTOC):
1208
1209    def __init__(self,conf,aw,showSessions=[],showDays=[],sortingCrit=None, ttPDFFormat=None,
1210                 pagesize='A4', fontsize = 'normal', firstPageNumber = '1', showSpeakerAffiliation=False, tz=None):
1211        self._conf=conf
1212        if not tz:
1213            self._tz = self._conf.getTimezone()
1214        else:
1215            self._tz = tz
1216        self._aw=aw
1217        self._tz = DisplayTZ(self._aw,self._conf).getDisplayTZ()
1218        self._showSessions=showSessions
1219        self._showDays=showDays
1220        self._ttPDFFormat = ttPDFFormat or TimetablePDFFormat()
1221        story=[]
1222        if self._ttPDFFormat.showCoverPage():
1223            story=None
1224        PDFWithTOC.__init__(self, story=story, pagesize = pagesize, fontsize=fontsize, firstPageNumber = firstPageNumber)
1225        self._title= _("Programme")
1226        self._doc.leftMargin=1*cm
1227        self._doc.rightMargin=1*cm
1228        self._doc.topMargin=1.5*cm
1229        self._doc.bottomMargin=1*cm
1230        self._sortingCrit=sortingCrit
1231        self._firstPageNumber = firstPageNumber
1232        self._showSpeakerAffiliation = showSpeakerAffiliation
1233
1234    def _processTOCPage(self):
1235        if self._ttPDFFormat.showTableContents():
1236            style1 = ParagraphStyle({})
1237            style1.fontName = "Times-Bold"
1238            style1.fontSize = modifiedFontSize(18, self._fontsize)
1239            style1.leading = modifiedFontSize(22, self._fontsize)
1240            style1.alignment = TA_CENTER
1241            self._story.append(Spacer(inch, 1*cm))
1242            p = Paragraph( _("Table of contents"), style1)
1243            self._story.append(p)
1244            self._story.append(Spacer(inch, 1*cm))
1245            if len(self._showSessions)>0:
1246                style2=ParagraphStyle({})
1247                style2.fontSize=modifiedFontSize(14, self._fontsize)
1248                style2.leading=modifiedFontSize(10, self._fontsize)
1249                style2.alignment=TA_CENTER
1250                caption=[]
1251                for sessionId in self._showSessions:
1252                    session=self._conf.getSessionById(sessionId)
1253                    if session is not None:
1254                        caption.append("%s"%escape(session.getTitle()))
1255                p=Paragraph("%s"%"\n".join(caption),style2)
1256                self._story.append(p)
1257            self._story.append(Spacer(inch, 2*cm))
1258            self._story.append(self._toc)
1259            self._story.append(PageBreak())
1260
1261    def firstPage(self,c,doc):
1262        if self._ttPDFFormat.showCoverPage():
1263            c.saveState()
1264            if HAVE_PIL and self._ttPDFFormat.showLogo():
1265                logo=self._conf.getLogo()
1266                imagePath=""
1267                if logo:
1268                    imagePath=logo.getFilePath()
1269                if imagePath:
1270                    img=Image.open(imagePath)
1271                    width,heigth=img.size
1272                    c.drawInlineImage(imagePath,self._PAGE_WIDTH/2.0-width/2,
1273                        self._PAGE_HEIGHT-inch-heigth)
1274            height=self._drawWrappedString(c, escape(self._conf.getTitle()))
1275            c.setFont('Times-Bold',modifiedFontSize(15, self._fontsize))
1276            height-=2*cm
1277            c.drawCentredString(self._PAGE_WIDTH/2.0,height,
1278                    "%s - %s"%(self._conf.getAdjustedStartDate(self._tz).strftime("%A %d %B %Y"),
1279                    self._conf.getAdjustedEndDate(self._tz).strftime("%A %d %B %Y")))
1280            if self._conf.getLocation():
1281                height-=2*cm
1282                c.drawCentredString(self._PAGE_WIDTH/2.0,height,escape(self._conf.getLocation().getName()))
1283            c.setFont('Times-Bold', modifiedFontSize(30, self._fontsize))
1284            height-=1*cm
1285            c.drawCentredString(self._PAGE_WIDTH/2.0,height,\
1286                    self._title)
1287            self._drawWrappedString(c, "%s / %s"%(self._conf.getTitle(),self._title), width=inch, height=0.75*inch, font='Times-Roman', size=modifiedFontSize(9, self._fontsize), color=(0.5,0.5,0.5), align="left", maximumWidth=self._PAGE_WIDTH-3.5*inch, measurement=inch, lineSpacing=0.15)
1288            c.drawRightString(self._PAGE_WIDTH-inch,0.75*inch,
1289                    nowutc().strftime("%A %d %B %Y"))
1290            c.restoreState()
1291
1292    def laterPages(self,c,doc):
1293
1294        c.saveState()
1295        maxi=self._PAGE_WIDTH-2*cm
1296        if doc.getCurrentPart().strip() != "":
1297            maxi=self._PAGE_WIDTH-6*cm
1298        self._drawWrappedString(c, "%s / %s"%(self._conf.getTitle(),self._title), width=1*cm, height=self._PAGE_HEIGHT-1*cm, font='Times-Roman', size=modifiedFontSize(9, self._fontsize), color=(0.5,0.5,0.5), align="left", lineSpacing=0.3, maximumWidth=maxi)
1299        c.drawCentredString(self._PAGE_WIDTH/2.0,0.5*cm,_(""" _("Page") %d """)%(doc.page + self._firstPageNumber - 1))
1300        c.drawRightString(self._PAGE_WIDTH-1*cm,self._PAGE_HEIGHT-1*cm,doc.getCurrentPart())
1301        c.restoreState()
1302
1303    def _defineStyles(self):
1304        self._styles={}
1305
1306        dayStyle=getSampleStyleSheet()["Heading1"]
1307        dayStyle.fontSize = modifiedFontSize(dayStyle.fontSize, self._fontsize)
1308        self._styles["day"]=dayStyle
1309
1310        sessionTitleStyle=getSampleStyleSheet()["Heading2"]
1311        sessionTitleStyle.fontSize = modifiedFontSize(12.0, self._fontsize)
1312        self._styles["session_title"]=sessionTitleStyle
1313
1314        sessionDescriptionStyle=getSampleStyleSheet()["Heading2"]
1315        sessionDescriptionStyle.fontSize = modifiedFontSize(10.0, self._fontsize)
1316        self._styles["session_description"] = sessionDescriptionStyle
1317
1318        self._styles["table_body"]=getSampleStyleSheet()["Normal"]
1319
1320        convenersStyle=getSampleStyleSheet()["Normal"]
1321        convenersStyle.fontSize = modifiedFontSize(10.0, self._fontsize)
1322        convenersStyle.leftIndent=10
1323        self._styles["conveners"]=convenersStyle
1324
1325        subContStyle=getSampleStyleSheet()["Normal"]
1326        subContStyle.fontSize=modifiedFontSize(10.0, self._fontsize)
1327        subContStyle.leftIndent=15
1328        self._styles["subContrib"]=subContStyle
1329
1330    def _HTMLColorToRGB(self, colorstring):
1331        """ convert #RRGGBB to an (R, G, B) tuple """
1332        colorstring = colorstring.strip()
1333        if colorstring[0] == '#': colorstring = colorstring[1:]
1334        if len(colorstring) != 6:
1335            raise ValueError, "input #%s is not in #RRGGBB format" % colorstring
1336        r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:]
1337        r, g, b = [float(int(n, 16))/256 for n in (r, g, b)]
1338        #raise MaKaCError(str((r,g,b)))
1339        return (r, g, b)
1340
1341    def _getSessionColor(self,ses):
1342        HTMLcolor = ses.getSession().getColor()
1343        color = self._HTMLColorToRGB(HTMLcolor)
1344        return color
1345
1346    def _processContribution(self,contrib,l):
1347        if not contrib.canAccess(self._aw):
1348            return
1349        date = "%s"%escape(contrib.getAdjustedStartDate(self._tz).strftime("%H:%M"))
1350        #date="<font size=\"" + str(modifiedFontSize(10, self._fontsize)) + "\">%s</font>"%date
1351        #date=self._fontify(date,10)
1352        #date.style=self._styles["table_body"]
1353        date=Paragraph(date,self._styles["table_body"])
1354        lt=[]
1355        captionText="[%s] %s"%(escape(contrib.getId()),escape(contrib.getTitle()))
1356        if not self._ttPDFFormat.showContribId():
1357            captionText="%s"%(escape(contrib.getTitle()))
1358        if self._ttPDFFormat.showLengthContribs():
1359            captionText="%s (%s)"%(captionText, escape((datetime(1900,1,1)+contrib.getDuration()).strftime("%Hh%M'")))
1360        if self._ttPDFFormat.showContribAbstract():
1361            captionText="<font name=\"Times-Bold\"><b>%s</b></font>"%captionText
1362        captionText="<font size=\"" + str(modifiedFontSize(10, self._fontsize)) + "\">%s</font>"%captionText
1363        lt.append([self._fontify(captionText,10)])
1364        colorCell = ""
1365        if self._useColors():
1366            colorCell = " "
1367        if self._ttPDFFormat.showContribAbstract():
1368            spkList=[]
1369            for spk in contrib.getSpeakerList():
1370                spkName = spk.getFullName()
1371                if not self._ttPDFFormat.showSpeakerTitle():
1372                    spkName = self._getNameWithoutTitle(spk)
1373                spkList.append(spkName)
1374            if len(spkList) > 0:
1375                if len(spkList) == 1:
1376                    speakerWord = _(""" _("Speaker"): """)
1377                else:
1378                    speakerWord = _(""" _("Speakers"): """)
1379                speakerText = speakerWord + ", ".join(spkList)
1380                speakerText = "<font name=\"Times-Italic\"><i>%s</i></font>"%speakerText
1381                lt.append([self._fontify(speakerText,9)])
1382            captionText=escape(contrib.getDescription())
1383            lt.append([self._fontify(captionText,9)])
1384            captionAndSpeakers = Table(lt,colWidths=(None),style=self._tsSpk)
1385            if colorCell != "":
1386                l.append([colorCell,date,captionAndSpeakers])
1387            else:
1388                l.append([date,captionAndSpeakers])
1389        else:
1390            caption = Table(lt,colWidths=(None),style=self._tsSpk)
1391            spkList=[]
1392            for spk in contrib.getSpeakerList():
1393                spkName = spk.getFullName()
1394                if not self._ttPDFFormat.showSpeakerTitle():
1395                    spkName = self._getNameWithoutTitle(spk)
1396                p=Paragraph(escape(spkName),self._styles["table_body"])
1397                spkList.append([p])
1398            if len(spkList)==0:
1399                spkList=[[""]]
1400            speakers=Table(spkList,style=self._tsSpk)
1401            if colorCell != "":
1402                l.append([colorCell,date,caption,speakers])
1403            else:
1404                l.append([date,caption,speakers])
1405        for subc in contrib.getSubContributionList():
1406            if not subc.canAccess(self._aw):
1407                return
1408            lt=[]
1409            captionText="- [%s] %s"%(escape(subc.getId()),escape(subc.getTitle()))
1410            if not self._ttPDFFormat.showContribId():
1411                captionText="- %s"%(escape(subc.getTitle()))
1412            if self._ttPDFFormat.showLengthContribs():
1413                captionText="%s (%s)"%(captionText, escape((datetime(1900,1,1)+subc.getDuration()).strftime("%Hh%M'")))
1414            captionText="<font size=\"" + str(modifiedFontSize(10, self._fontsize)) + "\">%s</font>"%captionText
1415            lt.append([Paragraph(captionText,self._styles["subContrib"])])
1416            if self._ttPDFFormat.showContribAbstract():
1417                captionText="<font size=\"" + str(modifiedFontSize(9, self._fontsize)) + "\">%s</font>"%(escape(subc.getDescription()))
1418                lt.append([Paragraph(captionText,self._styles["subContrib"])])
1419            spkList=[]
1420            for spk in subc.getSpeakerList():
1421                spkName = spk.getFullName()
1422                if not self._ttPDFFormat.showSpeakerTitle():
1423                    spkName = self._getNameWithoutTitle(spk)
1424                p=Paragraph(escape(spkName),self._styles["table_body"])
1425                spkList.append([p])
1426            if len(spkList)==0:
1427                spkList=[[""]]
1428            if self._ttPDFFormat.showContribAbstract():
1429                lt = spkList+lt
1430                captionAndSpeakers = Table(lt,colWidths=(None),style=self._tsSpk)
1431                if colorCell != "":
1432                    l.append([colorCell,"",captionAndSpeakers])
1433                else:
1434                    l.append(["",captionAndSpeakers])
1435            else:
1436                caption = Table(lt,colWidths=(None),style=self._tsSpk)
1437                speakers=Table(spkList,style=self._tsSpk)
1438                if colorCell != "":
1439                    l.append([colorCell,"",caption,speakers])
1440                else:
1441                    l.append(["",caption,speakers])
1442
1443
1444    def _processPosterContribution(self,contrib,l):
1445        if not contrib.canAccess(self._aw):
1446            return
1447        lt=[]
1448        captionText="[%s] %s"%(escape(contrib.getId()),escape(contrib.getTitle()))
1449        if not self._ttPDFFormat.showContribId():
1450            captionText="%s"%(escape(contrib.getTitle()))
1451        if self._ttPDFFormat.showLengthContribs():
1452            captionText="%s (%s)"%(captionText, escape((datetime(1900,1,1)+contrib.getDuration()).strftime("%Hh%M'")))
1453        captionText="<font name=\"Times-Bold\">%s</font>"%captionText
1454        lt.append([self._fontify(captionText,10)])
1455        boardNumber="%s"%escape(contrib.getBoardNumber())
1456        if self._ttPDFFormat.showContribAbstract() and self._ttPDFFormat.showContribPosterAbstract():
1457            spkList=[]
1458            for spk in contrib.getSpeakerList():
1459                spkName = spk.getFullName()
1460                if not self._ttPDFFormat.showSpeakerTitle():
1461                    spkName = self._getNameWithoutTitle(spk)
1462                spkList.append(spkName)
1463            if len(spkList) > 0:
1464                if len(spkList) == 1:
1465                    speakerWord = _(""" _("Speaker"): """)
1466                else:
1467                    speakerWord = _(""" _("Speakers"): """)
1468                speakerText = speakerWord + ", ".join(spkList)
1469                speakerText = "<font name=\"Times-Italic\"><i>%s</i></font>"%speakerText
1470                lt.append([self._fontify(speakerText, 10)])
1471            captionText=escape(contrib.getDescription())
1472            lt.append([self._fontify(captionText,9)])
1473            captionAndSpeakers = Table(lt,colWidths=(None),style=self._tsSpk)
1474            if self._useColors():
1475                l.append([" ",captionAndSpeakers,boardNumber])
1476            else:
1477                l.append([captionAndSpeakers,boardNumber])
1478        else:
1479            caption = Table(lt,colWidths=(None),style=self._tsSpk)
1480            spkList=[]
1481            for spk in contrib.getSpeakerList():
1482                spkName = spk.getFullName()
1483                if not self._ttPDFFormat.showSpeakerTitle():
1484                    spkName = self._getNameWithoutTitle(spk)
1485                p=Paragraph(escape(spkName),self._styles["table_body"])
1486                spkList.append([p])
1487            if len(spkList)==0:
1488                spkList=[[""]]
1489            speakers=Table(spkList,style=self._tsSpk)
1490            if self._useColors():
1491                l.append([" ",caption,speakers, boardNumber])
1492            else:
1493                l.append([caption,speakers, boardNumber])
1494        for subc in contrib.getSubContributionList():
1495            if not subc.canAccess(self._aw):
1496                return
1497            lt=[]
1498            captionText="- [%s] %s"%(escape(subc.getId()),escape(subc.getTitle()))
1499            if not self._ttPDFFormat.showContribId():
1500                captionText="- %s"%(escape(subc.getTitle()))
1501            if self._ttPDFFormat.showLengthContribs():
1502                captionText="%s (%s)"%(captionText, escape((datetime(1900,1,1)+subc.getDuration()).strftime("%Hh%M'")))
1503            lt.append([Paragraph(captionText,self._styles["subContrib"])])
1504            if self._ttPDFFormat.showContribAbstract():
1505                captionText="<font size=\"" + str(modifiedFontSize(9, self._fontsize)) + "\">%s</font>"%(escape(subc.getDescription()))
1506                lt.append([Paragraph(captionText,self._styles["subContrib"])])
1507            caption = Table(lt,colWidths=(None),style=self._tsSpk)
1508            spkList=[]
1509            for spk in subc.getSpeakerList():
1510                spkName = spk.getFullName()
1511                if not self._ttPDFFormat.showSpeakerTitle():
1512                    spkName = self._getNameWithoutTitle(spk)
1513                p=Paragraph(escape(spkName),self._styles["table_body"])
1514                spkList.append([p])
1515            if len(spkList)==0:
1516                spkList=[[""]]
1517            speakers=Table(spkList,style=self._tsSpk)
1518            l.append(["",caption,speakers])
1519
1520    def _getNameWithoutTitle(self, av):
1521        res = av.getFamilyName().upper()
1522        if av.getFirstName() != "":
1523            res = "%s, %s"%( res, av.getFirstName() )
1524        return res
1525
1526    def _useColors(self):
1527        return self._ttPDFFormat.showUseSessionColorCodes()
1528
1529    def _fontify(self, text, fSize=10, fName=""):
1530        style = getSampleStyleSheet()["Normal"]
1531        style.fontSize=modifiedFontSize(fSize, self._fontsize)
1532        style.leading=modifiedFontSize(fSize+3, self._fontsize)
1533        return Paragraph(text,style)
1534
1535    def _fontifyRow(self, row, fSize=10, fName=""):
1536        newrow = []
1537        for text in row:
1538            newrow.append(self._fontify(text,fSize,fName))
1539        return newrow
1540
1541    def _processDayEntries(self,day,story):
1542        res=[]
1543        originalts=TableStyle([('VALIGN',(0,0),(-1,-1),"TOP"),
1544                        ('LEFTPADDING',(0,0),(-1,-1),1),
1545                        ('RIGHTPADDING',(0,0),(-1,-1),1),
1546                        ('GRID',(0,1),(-1,-1),1,colors.lightgrey)])
1547        self._tsSpk=TableStyle([("LEFTPADDING",(0,0),(0,-1),0),
1548                            ("RIGHTPADDING",(0,0),(0,-1),0),
1549                            ("TOPPADDING",(0,0),(0,-1),1),
1550                            ("BOTTOMPADDING",(0,0),(0,-1),0)])
1551        colorts=TableStyle([("LEFTPADDING",(0,0),(-1,-1),3),
1552                            ("RIGHTPADDING",(0,0),(-1,-1),0),
1553                            ("TOPPADDING",(0,0),(-1,-1),0),
1554                            ("BOTTOMPADDING",(0,0),(-1,-1),0),
1555                            ('GRID',(0,0),(0,-1),1,colors.lightgrey)])
1556        entriesOnDay=self._conf.getSchedule().getEntriesOnDay(day)
1557        entriesOnDay.sort(sortEntries)
1558        for entry in entriesOnDay:
1559            #Session slot
1560            if isinstance(entry,schedule.LinkedTimeSchEntry) and \
1561                    isinstance(entry.getOwner(),conference.SessionSlot):
1562                sessionSlot=entry.getOwner()
1563                if len(self._showSessions)>0 and \
1564                    sessionSlot.getSession().getId() not in self._showSessions:
1565                    continue
1566                if not sessionSlot.canView(self._aw):
1567                    continue
1568                room=""
1569                if sessionSlot.getRoom() is not None:
1570                    room=" - %s"%escape(sessionSlot.getRoom().getName())
1571                sesCaption="%s"%sessionSlot.getSession().getTitle()
1572                if sessionSlot.getTitle()!="":
1573                    sesCaption="%s: %s"%(sesCaption,sessionSlot.getTitle())
1574                conv=[]
1575                for c in sessionSlot.getConvenerList():
1576                    if self._showSpeakerAffiliation:
1577                        conv.append("%s (%s)"%(escape(c.getFullName()), escape(c.getAffiliation())))
1578                    else:
1579                        conv.append(escape(c.getFullName()))
1580                conv="; ".join(conv)
1581                if conv!="":
1582                    conv=_("""<font name=\"Times-Bold\"><b>- _("Conveners"): %s</b></font>""")%conv
1583                res.append(Paragraph("",self._styles["session_title"]))
1584                startDateStr = escape(sessionSlot.getAdjustedStartDate(self._tz).strftime("%H:%M"))
1585                if self._ttPDFFormat.showDateCloseToSessions():
1586                    startDateStr = escape(sessionSlot.getAdjustedStartDate(self._tz).strftime("%d %B %H:%M"))
1587                text="""<u>%s</u>%s (%s-%s)"""%(
1588                        escape(sesCaption),room,
1589                        #escape(sessionSlot.getStartDate().strftime("%d %B %H:%M")),
1590                        #escape(sessionSlot.getEndDate().strftime("%H:%M")))
1591                        startDateStr,
1592                        escape(sessionSlot.getAdjustedEndDate(self._tz).strftime("%H:%M")))
1593                p1=Paragraph(text,self._styles["session_title"])
1594                if self._useColors():
1595                    l = [["",p1]]
1596                    widths=[0.2*cm,None]
1597                    ts = deepcopy(colorts)
1598                    ts.add('BACKGROUND', (0, 0), (0,-1), self._getSessionColor(sessionSlot))
1599                    p1 = Table(l,colWidths=widths,style=ts)
1600                res.append(p1)
1601                if self._ttPDFFormat.showTitleSessionTOC():
1602                    self._indexedFlowable[p1]={"text":escape(sessionSlot.getSession().getTitle()), "level":2}
1603##                if self._useColors():
1604##                    l = [["",p1]]
1605##                    widths=[0.2*cm,None]
1606##                    ts = deepcopy(colorts)
1607##                    ts.add('BACKGROUND', (0, 0), (0,-1), self._getSessionColor(sessionSlot))
1608##                    res.append(Table(l,colWidths=widths,style=ts))
1609##                else:
1610##                    res.append(p1)
1611                #add session description
1612                if sessionSlot.getSession().getDescription():
1613                    text = "<i>%s</i>"%escape(sessionSlot.getSession().getDescription())
1614                    p = Paragraph(text,self._styles["session_description"])
1615                    res.append(p)
1616                p2=Paragraph(conv,self._styles["conveners"])
1617                res.append(p2)
1618                l=[]
1619                ts = deepcopy(originalts)
1620                if sessionSlot.getSession().getScheduleType()=="poster":
1621                    if self._sortingCrit is not None:
1622                        cl=[]
1623                        for sEntry in sessionSlot.getSchedule().getEntries():
1624                            if isinstance(sEntry,schedule.LinkedTimeSchEntry) and isinstance(sEntry.getOwner(),conference.Contribution):
1625                                cl.append(sEntry.getOwner())
1626                        f=filters.SimpleFilter(None,self._sortingCrit)
1627                        for contrib in f.apply(cl):
1628                            self._processPosterContribution(contrib,l)
1629                    else:
1630                        for sEntry in sessionSlot.getSchedule().getEntries():
1631                            if isinstance(sEntry,schedule.LinkedTimeSchEntry) and isinstance(sEntry.getOwner(),conference.Contribution):
1632                                contrib=sEntry.getOwner()
1633                                self._processPosterContribution(contrib,l)
1634                    if len(l)>0:
1635                        title = "[id] title"
1636                        if not self._ttPDFFormat.showContribId():
1637                            title = "title"
1638                        if self._ttPDFFormat.showContribAbstract() and self._ttPDFFormat.showContribPosterAbstract():
1639                            #presenter integrated in 1st column -> 2 columns only
1640                            row = [title,"board"]
1641                            widths=[None,1*cm]
1642                        else:
1643                            row = [title,"presenter","board"]
1644                            widths=[None,5*cm,1*cm]
1645                        row = self._fontifyRow(row,11)
1646                        if self._useColors():
1647                            row.insert(0,"")
1648                            widths.insert(0,0.2*cm)
1649                        l.insert(0,row)
1650                        if self._useColors():
1651                            ts.add('BACKGROUND', (0, 1), (0,-1), self._getSessionColor(sessionSlot))
1652                        t=Table(l,colWidths=widths,style=ts)
1653                else: #it's not a poster
1654                    for sEntry in sessionSlot.getSchedule().getEntries():
1655                        if isinstance(sEntry,schedule.LinkedTimeSchEntry) and isinstance(sEntry.getOwner(),conference.Contribution):
1656                            contrib=sEntry.getOwner()
1657                            self._processContribution(contrib,l)
1658                        elif isinstance(sEntry,schedule.BreakTimeSchEntry):
1659##                            date="%s"%escape(sEntry.getStartDate().strftime("%H:%M"))
1660##                            date=self._fontify(date,10)
1661                            date="%s"%escape(sEntry.getAdjustedStartDate(self._tz).strftime("%H:%M"))
1662                            date=self._fontify(date,10)
1663
1664                            lt=[]
1665                            captionText="%s"%escape(sEntry.getTitle())
1666                            if self._ttPDFFormat.showLengthContribs():
1667                                captionText="%s (%s)"%(captionText, escape((datetime(1900,1,1)+sEntry.getDuration()).strftime("%Hh%M'")))
1668                            lt.append([self._fontify(captionText,10)])
1669                            caption = Table(lt,colWidths=(None),style=self._tsSpk)
1670                            if self._ttPDFFormat.showContribAbstract():
1671                                row = [date,caption]
1672                            else:
1673                                row = [date,caption,""]
1674                            if self._useColors():
1675                                row.insert(0,"")
1676                            l.append(row)
1677                    if len(l)>0:
1678                        title = "[id] title"
1679                        if not self._ttPDFFormat.showContribId():
1680                            title = "title"
1681                        if self._ttPDFFormat.showContribAbstract():
1682                            #presenter integrated in 1st column -> 2 columns only
1683                            row = ["time",title]
1684                            widths = [1*cm,None]
1685                        else:
1686                            row = ["time",title,"presenter"]
1687                            widths = [1*cm,None,5*cm]
1688                        row = self._fontifyRow(row,11)
1689                        if self._useColors():
1690                            row.insert(0,"")
1691                            widths.insert(0,0.2*cm)
1692                        l.insert(0,row)
1693                        if self._useColors():
1694                            ts.add('BACKGROUND', (0, 1), (0,-1), self._getSessionColor(sessionSlot))
1695                        t=Table(l,colWidths=widths,style=ts)
1696                if len(l)>0:
1697                    res.append(t)
1698                    if self._ttPDFFormat.showNewPagePerSession():
1699                        res.append(PageBreak())
1700                elif entry == entriesOnDay[-1]: # if it is the last one, we do the page break and remove the previous one.
1701                    i=len(res)-1
1702                    while i>=0:
1703                        if isinstance(res[i], PageBreak):
1704                            del res[i]
1705                            break
1706                        i-=1
1707                    if self._ttPDFFormat.showNewPagePerSession():
1708                        res.append(PageBreak())
1709            #contribution
1710            elif self._ttPDFFormat.showContribsAtConfLevel() and \
1711                 isinstance(entry,schedule.LinkedTimeSchEntry) and \
1712                 isinstance(entry.getOwner(),conference.Contribution):
1713                contrib=entry.getOwner()
1714                if not contrib.canView(self._aw):
1715                        continue
1716                room=""
1717                if contrib.getRoom() is not None:
1718                    room=" - %s"%escape(contrib.getRoom().getName())
1719                caption="%s"%contrib.getTitle()
1720                spks=[]
1721                for c in contrib.getSpeakerList():
1722                    if self._showSpeakerAffiliation:
1723                        spks.append("%s (%s)"%(escape(c.getFullName()), escape(c.getAffiliation())))
1724                    else:
1725                        spks.append(escape(c.getFullName()))
1726                spks="; ".join(spks)
1727                if spks.strip()!="":
1728                    spks=_("""<font name=\"Times-Bold\"><b>- _("Speakers"): %s</b></font>""")%spks
1729                text="""<u>%s</u>%s (%s-%s)"""%(
1730                        escape(caption),room,
1731                        escape(contrib.getAdjustedStartDate(self._tz).strftime("%H:%M")),
1732                        escape(contrib.getAdjustedEndDate(self._tz).strftime("%H:%M")))
1733                p1=Paragraph(text,self._styles["session_title"])
1734                res.append(p1)
1735                if self._ttPDFFormat.showTitleSessionTOC():
1736                    self._indexedFlowable[p1]={"text":escape(contrib.getTitle()), "level":2}
1737                p2=Paragraph(spks,self._styles["conveners"])
1738                res.append(p2)
1739                if entry == entriesOnDay[-1]: # if it is the last one, we do the page break and remove the previous one.
1740                    i=len(res)-1
1741                    while i>=0:
1742                        if isinstance(res[i], PageBreak):
1743                            del res[i]
1744                            break
1745                        i-=1
1746                    if self._ttPDFFormat.showNewPagePerSession():
1747                        res.append(PageBreak())
1748            #break
1749            elif self._ttPDFFormat.showBreaksAtConfLevel() and \
1750                 isinstance(entry,schedule.BreakTimeSchEntry):
1751                breakE=entry
1752                room=""
1753                if breakE.getRoom() is not None:
1754                    room=" - %s"%escape(breakE.getRoom().getName())
1755                caption="%s"%breakE.getTitle()
1756                text="""<u>%s</u>%s (%s-%s)"""%(
1757                        escape(caption),room,
1758                        escape(breakE.getAdjustedStartDate(self._tz).strftime("%H:%M")),
1759                        escape(breakE.getAdjustedEndDate(self._tz).strftime("%H:%M")))
1760                p1=Paragraph(text,self._styles["session_title"])
1761                res.append(p1)
1762                if self._ttPDFFormat.showTitleSessionTOC():
1763                    self._indexedFlowable[p1]={"text":escape(breakE.getTitle()), "level":2}
1764                if entry == entriesOnDay[-1]: # if it is the last one, we do the page break and remove the previous one.
1765                    i=len(res)-1
1766                    while i>=0:
1767                        if isinstance(res[i], PageBreak):
1768                            del res[i]
1769                            break
1770                        i-=1
1771                    if self._ttPDFFormat.showNewPagePerSession():
1772                        res.append(PageBreak())
1773
1774        return res
1775
1776
1777    def getBody(self,story=None):
1778        self._defineStyles()
1779        if not story:
1780            story=self._story
1781        if not self._ttPDFFormat.showCoverPage():
1782            s = ParagraphStyle({})
1783            s.fontName = "Times-Bold"
1784            s.fontSize = 18
1785            s.leading = 22
1786            s.alignment = TA_CENTER
1787            p=Paragraph(escape(self._conf.getTitle()),s)
1788            story.append(p)
1789            story.append(Spacer(1,0.4*inch))
1790
1791        currentDay=self._conf.getSchedule().getAdjustedStartDate(self._tz)
1792        while currentDay.strftime("%Y-%m-%d")<=self._conf.getSchedule().getAdjustedEndDate(self._tz).strftime("%Y-%m-%d"):
1793            if len(self._showDays)>0 and \
1794                    currentDay.strftime("%d-%B-%Y") not in self._showDays:
1795                currentDay+=timedelta(days=1)
1796                continue
1797            dayEntries=self._processDayEntries(currentDay,story)
1798            if len(dayEntries)==0:
1799                currentDay+=timedelta(days=1)
1800                continue
1801            text=escape(currentDay.strftime("%A %d %B %Y"))
1802            p=Paragraph(text,self._styles["day"],part=currentDay.strftime("%A %d %B %Y"))
1803            story.append(p)
1804            self._indexedFlowable[p]={"text":currentDay.strftime("%A %d %B %Y"), "level":1}
1805            for entry in dayEntries:
1806                story.append(entry)
1807            if not self._ttPDFFormat.showNewPagePerSession():
1808                story.append(PageBreak())
1809            currentDay+=timedelta(days=1)
1810
1811class SimplifiedTimeTablePlain(PDFBase):
1812
1813    def __init__(self,conf,aw,showSessions=[],showDays=[],sortingCrit=None, ttPDFFormat=None, pagesize = 'A4', fontsize = 'normal', tz=None):
1814        self._conf=conf
1815        if not tz:
1816            self._tz = self._conf.getTimezone()
1817        else:
1818            self._tz = tz
1819        self._aw=aw
1820        self._showSessions=showSessions
1821        self._showDays=showDays
1822        PDFBase.__init__(self, story=[], pagesize = pagesize)
1823        self._title= _("Simplified Programme")
1824        self._doc.leftMargin=1*cm
1825        self._doc.rightMargin=1*cm
1826        self._doc.topMargin=1*cm
1827        self._doc.bottomMargin=1*cm
1828        self._sortingCrit=sortingCrit
1829        self._ttPDFFormat = ttPDFFormat or TimetablePDFFormat()
1830        self._fontsize = fontsize
1831
1832    def _defineStyles(self):
1833        self._styles={}
1834        normalStl=getSampleStyleSheet()["Normal"]
1835        normalStl.fontName="Courier"
1836        normalStl.fontSize = modifiedFontSize(10, self._fontsize)
1837        normalStl.spaceBefore=0
1838        normalStl.spaceAfter=0
1839        normalStl.alignment=TA_LEFT
1840        self._styles["normal"]=normalStl
1841        titleStl=getSampleStyleSheet()["Normal"]
1842        titleStl.fontName="Courier-Bold"
1843        titleStl.fontSize = modifiedFontSize(12, self._fontsize)
1844        titleStl.spaceBefore=0
1845        titleStl.spaceAfter=0
1846        titleStl.alignment=TA_LEFT
1847        self._styles["title"]=titleStl
1848        dayStl=getSampleStyleSheet()["Normal"]
1849        dayStl.fontName="Courier-Bold"
1850        dayStl.fontSize = modifiedFontSize(10, self._fontsize)
1851        dayStl.spaceBefore=0
1852        dayStl.spaceAfter=0
1853        dayStl.alignment=TA_LEFT
1854        self._styles["day"]=dayStl
1855
1856    def _haveSessionSlotsTitles(self, session):
1857        """Checks if the session has slots with titles or not"""
1858        for ss in session.getSlotList():
1859            if ss.getTitle().strip() != "":
1860                return True
1861        return False
1862
1863    def _processDayEntries(self,day,story):
1864        lastSessions=[] # this is to avoid checking if the slots have titles for all the slots
1865        res=[]
1866        for entry in self._conf.getSchedule().getEntriesOnDay(day):
1867            if isinstance(entry,schedule.LinkedTimeSchEntry) and \
1868                    isinstance(entry.getOwner(),conference.SessionSlot):
1869                sessionSlot=entry.getOwner()
1870                session = sessionSlot.getSession()
1871                if len(self._showSessions)>0 and \
1872                    session.getId() not in self._showSessions:
1873                    continue
1874                if not sessionSlot.canView(self._aw):
1875                    continue
1876                if session in lastSessions:
1877                    continue
1878                if self._haveSessionSlotsTitles(session):
1879                    e=sessionSlot
1880                else:
1881                    lastSessions.append(session)
1882                    e=session
1883                title=e.getTitle()
1884                if title.strip()=="":
1885                    title=e.getOwner().getTitle()
1886                res.append(Paragraph( _("""<font name=\"Times-Bold\"><b> _("Session"):</b></font> %s""")%escape(title),self._styles["normal"]))
1887                roomTime=""
1888                if e.getRoom() is not None:
1889                    roomTime="%s "%(escape(e.getRoom().getName()))
1890                roomTime= _("""<font name=\"Times-Bold\"><b> _("Time and Place"):</b></font> %s(%s-%s)""")%(roomTime, e.getAdjustedStartDate(self._tz).strftime("%H:%M"), \
1891                        e.getAdjustedEndDate(self._tz).strftime("%H:%M"))
1892                res.append(Paragraph(roomTime,self._styles["normal"]))
1893                chairs=[]
1894                for c in e.getConvenerList():
1895                    chairs.append("%s"%c.getFullName())
1896                if chairs != []:
1897                    res.append(Paragraph( _("""<font name=\"Times-Bold\"><b> _("Chair/s"):</b></font> %s""")%("; ".join(chairs)),self._styles["normal"]))
1898                res.append(Spacer(1,0.2*inch))
1899            elif self._ttPDFFormat.showContribsAtConfLevel() and isinstance(entry,schedule.LinkedTimeSchEntry) and \
1900                    isinstance(entry.getOwner(),conference.Contribution):
1901                contrib=entry.getOwner()
1902                if not contrib.canView(self._aw):
1903                    continue
1904                title=contrib.getTitle()
1905                if title.strip()=="":
1906                    title=e.getOwner().getTitle()
1907                res.append(Paragraph( _("""<font name=\"Times-Bold\"><b> _("Contribution"):</b></font> %s""")%escape(title),self._styles["normal"]))
1908                roomTime=""
1909                if contrib.getRoom() is not None:
1910                    roomTime="%s "%(escape(contrib.getRoom().getName()))
1911                roomTime= _("""<font name=\"Times-Bold\"><b> _("Time and Place"):</b></font> %s(%s-%s)""")%(roomTime, contrib.getAdjustedStartDate(self._tz).strftime("%H:%M"), \
1912                        contrib.getAdjustedEndDate(self._tz).strftime("%H:%M"))
1913                res.append(Paragraph(roomTime,self._styles["normal"]))
1914                spks=[]
1915                for c in contrib.getSpeakerList():
1916                    spks.append("%s"%c.getFullName())
1917                if spks != []:
1918                    res.append(Paragraph( _("""<font name=\"Times-Bold\"><b> _("Speaker/s"):</b></font> %s""")%("; ".join(spks)),self._styles["normal"]))
1919                res.append(Spacer(1,0.2*inch))
1920            elif self._ttPDFFormat.showBreaksAtConfLevel() and isinstance(entry,schedule.BreakTimeSchEntry):
1921                title=entry.getTitle()
1922                if title.strip()=="":
1923                    title=e.getOwner().getTitle()
1924                res.append(Paragraph( _("""<font name=\"Times-Bold\"><b> _("Break"):</b></font> %s""")%escape(title),self._styles["normal"]))
1925                roomTime=""
1926                if entry.getRoom() is not None:
1927                    roomTime="%s "%(escape(entry.getRoom().getName()))
1928                roomTime= _("""<font name=\"Times-Bold\"><b> _("Time and Place"):</b></font> %s(%s-%s)""")%(roomTime, entry.getAdjustedStartDate(self._tz).strftime("%H:%M"), \
1929                        entry.getAdjustedEndDate(self._tz).strftime("%H:%M"))
1930                res.append(Paragraph(roomTime,self._styles["normal"]))
1931                res.append(Spacer(1,0.2*inch))
1932        res.append(PageBreak())
1933        return res
1934
1935    def getBody(self,story=None):
1936        self._defineStyles()
1937        if not story:
1938            story=self._story
1939        currentDay=self._conf.getSchedule().getAdjustedStartDate(self._tz)
1940        while currentDay.strftime("%Y-%m-%d")<=self._conf.getSchedule().getAdjustedEndDate(self._tz).strftime("%Y-%m-%d"):
1941            if len(self._showDays)>0 and \
1942                    currentDay.strftime("%d-%B-%Y") not in self._showDays:
1943                currentDay+=timedelta(days=1)
1944                continue
1945            dayEntries=self._processDayEntries(currentDay,story)
1946            if len(dayEntries)==0:
1947                currentDay+=timedelta(days=1)
1948                continue
1949            if self._conf.getAdjustedEndDate(self._tz).month != self._conf.getAdjustedEndDate(self._tz).month:
1950                text="%s - %s-%s"%(escape(self._conf.getTitle()), escape(self._conf.getAdjustedStartDate(self._tz).strftime("%d %B %Y")), \
1951                    escape(self._conf.getAdjustedEndDate(self._tz).strftime("%d %B %Y")) )
1952            else:
1953                text="%s - %s-%s"%(escape(self._conf.getTitle()), escape(self._conf.getAdjustedStartDate(self._tz).strftime("%d")), \
1954                        escape(self._conf.getAdjustedEndDate(self._tz).strftime("%d %B %Y")) )
1955            if self._conf.getLocation() is not None:
1956                text="%s, %s."%(text, self._conf.getLocation().getName())
1957            text="%s"%text
1958            p=Paragraph(text, self._styles["title"])
1959            story.append(p)
1960            text2= _(""" _("Daily Programme"): %s""")%escape(currentDay.strftime("%A %d %B %Y"))
1961            p2=Paragraph(text2,self._styles["day"])
1962            story.append(p2)
1963            story.append(Spacer(1,0.4*inch))
1964            for entry in dayEntries:
1965                story.append(entry)
1966            currentDay+=timedelta(days=1)
1967
1968class AbstractBook(PDFBase):
1969
1970    def __init__(self,conf,aw,sortBy,tz=None):
1971        self._conf=conf
1972        if not tz:
1973            self._tz = self._conf.getTimezone()
1974        else:
1975            self._tz = tz
1976        self._aw=aw
1977        self._sortBy=sortBy
1978        if sortBy.strip()=="" or\
1979                sortBy not in ["number", "name", "sessionTitle", "speaker", "schedule"]:
1980            self._sortBy="number"
1981        PDFBase.__init__(self)
1982        self._title= _("Book of abstracts")
1983        self._doc.leftMargin=1*cm
1984        self._doc.rightMargin=1*cm
1985        self._doc.topMargin=1.5*cm
1986        self._doc.bottomMargin=1*cm
1987
1988    def firstPage(self,c,doc):
1989        c.saveState()
1990        if HAVE_PIL:
1991            logo=self._conf.getLogo()
1992            imagePath=""
1993            if logo:
1994                imagePath=logo.getFilePath()
1995            if imagePath:
1996                img=Image.open(imagePath)
1997                width,heigth=img.size
1998                c.drawInlineImage(imagePath,self._PAGE_WIDTH/2.0-width/2,self._PAGE_HEIGHT-inch-heigth)
1999        height=self._drawWrappedString(c,self._conf.getTitle())
2000        c.setFont('Times-Bold',15)
2001        height-=2*cm
2002        c.drawCentredString(self._PAGE_WIDTH/2.0,height,
2003                "%s - %s"%(self._conf.getAdjustedStartDate(self._tz).strftime("%A %d %B %Y"),
2004                self._conf.getAdjustedEndDate(self._tz).strftime("%A %d %B %Y")))
2005        if self._conf.getLocation():
2006            height-=1*cm
2007            c.drawCentredString(self._PAGE_WIDTH/2.0,height,
2008                    escape(self._conf.getLocation().getName()))
2009        c.setFont('Times-Bold', 30)
2010        height-=6*cm
2011        c.drawCentredString(self._PAGE_WIDTH/2.0,height,\
2012                self._title)
2013        self._drawWrappedString(c, "%s / %s"%(self._conf.getTitle(),self._title), width=inch, height=0.75*inch, font='Times-Roman', size=9, color=(0.5,0.5,0.5), align="left", maximumWidth=self._PAGE_WIDTH-3.5*inch, measurement=inch, lineSpacing=0.15)
2014        c.drawRightString(self._PAGE_WIDTH-inch,0.75*inch,
2015                nowutc().strftime("%A %d %B %Y"))
2016        c.restoreState()
2017
2018    def laterPages(self,c,doc):
2019        c.saveState()
2020        c.setFont('Times-Roman',9)
2021        c.setFillColorRGB(0.5,0.5,0.5)
2022        c.drawString(1*cm,self._PAGE_HEIGHT-1*cm,
2023            "%s / %s"%(escape(self._conf.getTitle()),self._title))
2024        c.drawCentredString(self._PAGE_WIDTH/2.0,0.5*cm,"Page %d "%doc.page)
2025        c.restoreState()
2026
2027    def _defineStyles(self):
2028        self._styles={}
2029        titleStyle=getSampleStyleSheet()["Heading1"]
2030        titleStyle.fontSize=13.0
2031        titleStyle.spaceBefore=0
2032        titleStyle.spaceAfter=4
2033        titleStyle.leading=14
2034        self._styles["title"]=titleStyle
2035        spkStyle=getSampleStyleSheet()["Heading2"]
2036        spkStyle.fontSize=10.0
2037        spkStyle.spaceBefore=0
2038        spkStyle.spaceAfter=0
2039        spkStyle.leading=14
2040        self._styles["speakers"]=spkStyle
2041        abstractStyle=getSampleStyleSheet()["Normal"]
2042        abstractStyle.fontSize=10.0
2043        abstractStyle.spaceBefore=0
2044        abstractStyle.spaceAfter=0
2045        abstractStyle.alignment=TA_LEFT
2046        self._styles["abstract"]=abstractStyle
2047        ttInfoStyle=getSampleStyleSheet()["Normal"]
2048        ttInfoStyle.fontSize=10.0
2049        ttInfoStyle.spaceBefore=0
2050        ttInfoStyle.spaceAfter=0
2051        self._styles["tt_info"]=ttInfoStyle
2052        normalStyle=getSampleStyleSheet()["Normal"]
2053        normalStyle.fontSize=10.0
2054        normalStyle.spaceBefore=5
2055        normalStyle.spaceAfter=5
2056        normalStyle.alignment=TA_LEFT
2057        self._styles["normal"]=normalStyle
2058
2059    def _addContribution(self, contrib, story):
2060        if not contrib.canAccess(self._aw):
2061            return
2062        caption="%s - %s"%(contrib.getId(),contrib.getTitle())
2063        p1=Paragraph(escape(caption),self._styles["title"])
2064        lspk=[]
2065        for spk in contrib.getSpeakerList():
2066            fullName=spk.getFullName()
2067            instit=spk.getAffiliation().strip()
2068            if instit!="":
2069                fullName="%s (%s)"%(fullName, instit)
2070            lspk.append("%s"%escape(fullName))
2071        speakers= _("""<b> _("Presenter"): %s</b>""")%"; ".join(lspk)
2072        p2=Paragraph(speakers,self._styles["speakers"])
2073        abstract=contrib.getDescription()
2074        p3=Paragraph(escape(abstract),self._styles["abstract"])
2075        if contrib.isScheduled():
2076            ses=""
2077            if contrib.getSession() is not None:
2078                ses="%s - "%contrib.getSession().getTitle()
2079            text="%s%s"%(ses,contrib.getAdjustedStartDate(self._tz).strftime("%A %d %B %Y %H:%M"))
2080            p4=Paragraph(escape(text),self._styles["tt_info"])
2081            abs=KeepTogether([p1,p4,p2,p3])
2082        else:
2083            abs=KeepTogether([p1,p2,p3])
2084        story.append(abs)
2085        story.append(Spacer(1,0.4*inch))
2086
2087    def getBody(self,story=None):
2088        self._defineStyles()
2089        if not story:
2090            story=self._story
2091        story.append(PageBreak())
2092        if self._conf.getBOAConfig().getText():
2093            text=self._conf.getBOAConfig().getText().replace("<BR>","<br>")
2094            text=text.replace("<Br>","<br>")
2095            text=text.replace("<bR>","<br>")
2096            for par in text.split("<br>"):
2097                p=Paragraph(par,self._styles["normal"])
2098                story.append(p)
2099            story.append(PageBreak())
2100        if self._sortBy == "schedule":
2101            for entry in self._conf.getSchedule().getEntries():
2102                if isinstance(entry,schedule.LinkedTimeSchEntry) and isinstance(entry.getOwner(),conference.SessionSlot):
2103                    if entry.getOwner().canAccess(self._aw):
2104                        for slotentry in entry.getOwner().getSchedule().getEntries():
2105                            if isinstance(slotentry.getOwner(), conference.Contribution):
2106                                self._addContribution(slotentry.getOwner(), story)
2107                elif isinstance(entry,schedule.LinkedTimeSchEntry) and isinstance(entry.getOwner(),conference.Contribution):
2108                    self._addContribution(entry.getOwner(), story)
2109        else:
2110            fc=FilterCriteria(self._conf,{"status":[ContribStatusList.getId(conference.ContribStatusSch),ContribStatusList.getId(conference.ContribStatusNotSch)]})
2111            sc=contribFilters.SortingCriteria((self._sortBy,))
2112            f=filters.SimpleFilter(fc,sc)
2113            for contrib in f.apply(self._conf.getContributionList()):
2114                self._addContribution(contrib, story)
2115
2116
2117class FilterCriteria(filters.FilterCriteria):
2118    _availableFields = {
2119        contribFilters.StatusFilterField.getId():contribFilters.StatusFilterField
2120                }
2121
2122class ProceedingsTOC(PDFBase):
2123
2124    def __init__(self, conf, trackDict=None, trackOrder=None, contribList=None, npages=None, doc=None, story=None, tz=None):
2125        self._conf = conf
2126        if not tz:
2127            self._tz = self._conf.getTimezone()
2128        else:
2129            self._tz = tz
2130        self._trackDict = trackDict
2131        self._trackOrder = trackOrder
2132        self._contribDictNPages = npages
2133        self._contribList=contribList
2134        if not story:
2135            story = [Spacer(inch, 5*cm)]
2136        PDFBase.__init__(self, doc, story)
2137        self._title = _("Proceedings")
2138        self._PAGE_HEIGHT = defaultPageSize[1]
2139        self._PAGE_WIDTH = defaultPageSize[0]
2140
2141    def firstPage(self,c,doc):
2142        c.saveState()
2143        if HAVE_PIL:
2144            logo=self._conf.getLogo()
2145            imagePath=""
2146            if logo:
2147                imagePath=logo.getFilePath()
2148            if imagePath:
2149                img=Image.open(imagePath)
2150                width,heigth=img.size
2151                c.drawInlineImage(imagePath,self._PAGE_WIDTH/2.0-width/2,
2152                    self._PAGE_HEIGHT-inch-heigth)
2153        height=self._drawWrappedString(c, self._conf.getTitle())
2154        c.setFont('Times-Bold',15)
2155        height-=2*cm
2156        c.drawCentredString(self._PAGE_WIDTH/2.0,height,
2157                "%s - %s"%(self._conf.getAdjustedStartDate(self._tz).strftime("%A %d %B %Y"),
2158                self._conf.getAdjustedEndDate(self._tz).strftime("%A %d %B %Y")))
2159        if self._conf.getLocation():
2160            height-=1*cm
2161            c.drawCentredString(self._PAGE_WIDTH/2.0,height,escape(self._conf.getLocation().getName()))
2162        c.setFont('Times-Bold', 30)
2163        height-=6*cm
2164        c.drawCentredString(self._PAGE_WIDTH/2.0,height,self._title)
2165        c.setFont('Times-Roman',9)
2166        c.setFillColorRGB(0.5,0.5,0.5)
2167        c.restoreState()
2168
2169    def laterPages(self,c,doc):
2170        c.saveState()
2171        location = ""
2172        if self._conf.getLocation() is not None and self._conf.getLocation().getName().strip() != "":
2173            location = " - %s"%(escape(self._conf.getLocation().getName()))
2174        self._drawWrappedString(c, "%s%s"%(escape(self._conf.getTitle()), location), width=0.5*inch, height=self._PAGE_HEIGHT-0.75*inch, font='Times-Roman', size=9, color=(0.5,0.5,0.5), align="left", maximumWidth=self._PAGE_WIDTH-inch, measurement=inch, lineSpacing=0.15)
2175        c.drawCentredString(self._PAGE_WIDTH/2.0,0.5*cm,"%s "%Int2Romans.int_to_roman(doc.page-1))
2176        c.restoreState()
2177
2178    def getBody(self, story=None, indexedFlowable={}, level=1 ):
2179        if not story:
2180            story = self._story
2181        self._story.append(PageBreak())
2182        style = ParagraphStyle({})
2183        style.fontName = "Times-Bold"
2184        style.fontSize = 20
2185        style.spaceBefore=0
2186        style.spaceAfter=8
2187        style.leading=14
2188        style.alignment=TA_LEFT
2189        text = _("Table of Contents")
2190        p = Paragraph(text, style)
2191        story.append(p)
2192
2193        story.append(Spacer(inch, 0.5*cm))
2194
2195        styleAuthor = ParagraphStyle({})
2196        styleAuthor.leading = 10
2197        styleAuthor.fontName = "Times-Roman"
2198        styleAuthor.fontSize = 8
2199        styleAuthor.spaceBefore=0
2200        styleAuthor.spaceAfter=0
2201        styleAuthor.alignment=TA_LEFT
2202        styleAuthor.leftIndent=10
2203        styleAuthor.firstLineIndent=0
2204
2205        styleContrib = ParagraphStyle({})
2206        styleContrib.leading = 12
2207        styleContrib.fontName = "Times-Roman"
2208        styleContrib.fontSize = 10
2209        styleContrib.spaceBefore=0
2210        styleContrib.spaceAfter=0
2211        styleContrib.alignment=TA_LEFT
2212        styleContrib.leftIndent=0
2213        styleContrib.firstLineIndent=0
2214        styleContrib.leftIndent=0
2215
2216        styleTrack = ParagraphStyle({})
2217        styleTrack.fontName = "Times-Bold"
2218        styleTrack.fontSize = 12
2219        styleTrack.spaceBefore=40
2220        styleTrack.spaceAfter=30
2221        styleTrack.alignment=TA_LEFT
2222
2223        tsContribs=TableStyle([('VALIGN',(0,0),(-1,0),"BOTTOM"),
2224                        ('VALIGN',(0,0),(-1,-1),"BOTTOM"),
2225                        ('ALIGN',(0,1),(-1,1),"RIGHT"),
2226                        ('BOTTOMPADDING',(0,0),(-1,-1),0),
2227                        ('TOPPADDING',(0,0),(-1,-1),0)])
2228        i = 1
2229        if self._trackOrder is not None and self._trackOrder!=[]:
2230            for track in self._trackOrder:
2231                l=[]
2232                p=Paragraph("",styleTrack)
2233                p2=Paragraph("",styleTrack)
2234                l.append([p, p2])
2235                p=Paragraph(escape(track.getTitle()),styleTrack)
2236                p2=Paragraph("<b>%s</b>"%escape("%s"%i),styleTrack)
2237                i += 2
2238                l.append([p, p2])
2239                p=Paragraph("",styleTrack)
2240                p2=Paragraph("",styleTrack)
2241                l.append([p, p2])
2242                l.append(["", ""])
2243                for contrib in self._trackDict[track.getId()]:
2244                    i=self._addContrib(contrib, l, i, styleContrib, styleAuthor )
2245                l.append(["", ""])
2246                t=Table(l,colWidths=(None,1.2*cm),style=tsContribs)
2247                self._story.append(t)
2248        else:
2249            l=[]
2250            for contrib in self._contribList:
2251                i=self._addContrib(contrib, l, i, styleContrib, styleAuthor)
2252            if l!=[]:
2253                t=Table(l,colWidths=(None,1.2*cm),style=tsContribs)
2254                self._story.append(t)
2255        self._story.append(Spacer(inch, 2*cm))
2256
2257        return story
2258
2259    def _addContrib(self, contrib, l, i, styleContrib, styleAuthor):
2260        authorList = []
2261        for author in contrib.getPrimaryAuthorList():
2262            authorList.append(self._getAbrName(author))
2263        for author in contrib.getCoAuthorList():
2264            authorList.append(self._getAbrName(author))
2265        if authorList == []:
2266            for author in contrib.getSpeakerList():
2267                authorList.append(self._getAbrName(author))
2268        p=Paragraph(escape(contrib.getTitle()), styleContrib)
2269        p2=Paragraph("""<i>%s</i>"""%(escape(", ".join(authorList))), styleAuthor)
2270        p3=Paragraph("""<font size="10">%s</font>"""%escape("%s"%i),styleAuthor)
2271        i += self._contribDictNPages[contrib.getId()]
2272        l.append([p, ""])
2273        l.append([p2, p3])
2274        l.append(["", ""])
2275        return i
2276
2277    def _getAbrName(self, author):
2278        res = author.getFamilyName()
2279        if res.strip() != "" and len(res)>1:
2280            res = "%s%s"%(res[0].upper(), res[1:].lower())
2281        if author.getFirstName() != "":
2282            if res == "":
2283                res = author.getFirstName()
2284            else:
2285                res = "%s. %s"%(author.getFirstName()[0].upper(), res)
2286        return res
2287
2288class ProceedingsChapterSeparator(PDFBase):
2289
2290    def __init__(self, track, doc=None, story=None):
2291        self._track = track
2292        self._conf = track.getConference()
2293        if not story:
2294            story = [Spacer(inch, 5*cm)]
2295        PDFBase.__init__(self, doc, story)
2296        self._title = _("Proceedings")
2297        self._PAGE_HEIGHT = defaultPageSize[1]
2298        self._PAGE_WIDTH = defaultPageSize[0]
2299
2300    def firstPage(self,c,doc):
2301        c.saveState()
2302        c.setFont('Times-Roman',9)
2303        c.setFillColorRGB(0.5,0.5,0.5)
2304        #c.drawString(1*cm,self._PAGE_HEIGHT-1*cm,
2305        #    "%s / %s"%(escape(self._conf.getTitle()),self._title))
2306        #c.drawCentredString(self._PAGE_WIDTH/2.0,0.5*cm,"Page %d "%doc.page)
2307        self._drawWrappedString(c, self._track.getTitle())
2308        c.setFont('Times-Roman',9)
2309        c.setFillColorRGB(0.5,0.5,0.5)
2310        c.restoreState()
2311
2312    def laterPages(self,c,doc):
2313        c.saveState()
2314        c.setFont('Times-Roman',9)
2315        c.setFillColorRGB(0.5,0.5,0.5)
2316        #c.drawString(1*cm,self._PAGE_HEIGHT-1*cm,
2317        #    "%s / %s"%(escape(self._conf.getTitle()),self._title))
2318        #c.drawCentredString(self._PAGE_WIDTH/2.0,0.5*cm,"Page %d "%doc.page)
2319        c.restoreState()
2320
2321    def getBody(self, story=None, indexedFlowable={}, level=1 ):
2322        if not story:
2323            story = self._story
2324        self._story.append(PageBreak())
2325        self._story.append(PageBreak())
2326        return story
2327
2328class Int2Romans:
2329
2330    def int_to_roman(input):
2331        """
2332        Convert an integer to Roman numerals.
2333        """
2334        if type(input) != type(1):
2335            raise TypeError, _("expected integer, got %s") % type(input)
2336        if not 0 < input < 4000:
2337            raise MaKaCError( _("Int to Roman Error: Argument must be between 1 and 3999"))
2338        ints = (1000, 900,  500, 400, 100,  90, 50,  40, 10,  9,   5,  4,   1)
2339        nums = ('m',  'cm', 'd', 'cd','c', 'xc','l','xl','x','ix','v','iv','i')
2340        result = ""
2341        for i in range(len(ints)):
2342            count = int(input / ints[i])
2343            result += nums[i] * count
2344            input -= ints[i] * count
2345        return result
2346    int_to_roman = staticmethod(int_to_roman)
2347
2348
2349class RegistrantsListToPDF(PDFBase):
2350
2351    def __init__(self, conf,doc=None, story=[],list=None, display=["Institution", "Phone", "City", "Country"]):
2352        self._conf = conf
2353        self._regForm = conf.getRegistrationForm()
2354        self._regList = list
2355        self._display = display
2356        PDFBase.__init__(self, doc, story, printLandscape=True)
2357        self._title = _("Registrants List")
2358        self._PAGE_HEIGHT = landscape(A4)[1]
2359        self._PAGE_WIDTH = landscape(A4)[0]
2360
2361    def firstPage(self, c, doc):
2362        c.saveState()
2363        showLogo = False
2364        c.setFont('Times-Bold', 30)
2365        if not showLogo:
2366            self._drawWrappedString(c, escape(self._conf.getTitle()), height=self._PAGE_HEIGHT-0.75*inch)
2367        c.setFont('Times-Bold', 25)
2368        c.setLineWidth(3)
2369        c.setStrokeGray(0.7)
2370        c.setFont('Times-Roman', 10)
2371        c.drawRightString(self._PAGE_WIDTH - inch,self._PAGE_HEIGHT-1*cm, "%s"%(nowutc().strftime("%d %B %Y, %H:%M")))
2372        c.restoreState()
2373
2374    def getBody(self, story=None, indexedFlowable={}, level=1 ):
2375        if not story:
2376            story = self._story
2377
2378        style = ParagraphStyle({})
2379        style.fontSize = 12
2380        style.alignment = TA_CENTER
2381        text = _("""<b>_("List of registrants")</b>""")
2382        p = Paragraph(text, style, part=escape(self._conf.getTitle()))
2383        p.spaceAfter = 30
2384        story.append(p)
2385
2386        styleRegistrant = ParagraphStyle({})
2387        styleRegistrant.leading = 10
2388        styleRegistrant.fontName = "Times-Roman"
2389        styleRegistrant.fontSize = 8
2390        styleRegistrant.spaceBefore=0
2391        styleRegistrant.spaceAfter=0
2392        styleRegistrant.alignment=TA_LEFT
2393        styleRegistrant.leftIndent=10
2394        styleRegistrant.firstLineIndent=0
2395
2396        tsRegs=TableStyle([('VALIGN',(0,0),(-1,-1),"MIDDLE"),
2397                        ('LINEBELOW',(0,0),(-1,0), 1, colors.black),
2398                        ('ALIGN',(0,0),(-1,0),"CENTER"),
2399                        ('ALIGN',(0,1),(-1,-1),"LEFT") ] )
2400        l = []
2401        lp = []
2402        lp.append(Paragraph( _("""<b> _("Name")</b>"""), styleRegistrant))
2403
2404        for key in self._display:
2405            if key in ["Email", "Position", "LastName", "FirstName", "Institution", "Phone", "City", "Country", "Address", "RegistrationDate"]:
2406                p=Paragraph("""<b>%s</b>"""%key, styleRegistrant)
2407            elif key=="Accommodation":
2408                p=Paragraph("""<b>%s</b>"""%escape(self._regForm.getAccommodationForm().getTitle()), styleRegistrant)
2409            elif key == "SocialEvents":
2410                p=Paragraph("""<b>%s</b>"""%escape(self._regForm.getSocialEventForm().getTitle()), styleRegistrant)
2411            elif key == "Sessions":
2412                p=Paragraph("""<b>%s</b>"""%escape(self._regForm.getSessionsForm().getTitle()), styleRegistrant)
2413            elif key=="ArrivalDate":
2414                p=Paragraph( _("""<b> _("Arrival Date")</b>"""), styleRegistrant)
2415            elif key=="DepartureDate":
2416                p=Paragraph( _("""<b> _("Departure Date")</b>"""), styleRegistrant)
2417            elif key == "ReasonParticipation":
2418                p=Paragraph("""<b>%s</b>"""%escape(self._regForm.getReasonParticipationForm().getTitle()), styleRegistrant)
2419            elif key == "isPayed":
2420                p=Paragraph("""<b>Paid</b>""", styleRegistrant)
2421            elif key == "idpayment":
2422                p=Paragraph("""<b>Payment ID</b>""", styleRegistrant)
2423            elif key == "amountToPay":
2424                p=Paragraph("""<b>Amount</b>""", styleRegistrant)
2425            elif key.startswith("s-"):
2426                ids=key.split("-")
2427                if len(ids)==2:
2428                    status=self._regForm.getStatusById(ids[1])
2429                    p=Paragraph("""<b>%s</b>"""%escape(status.getCaption()), styleRegistrant)
2430                else:
2431                    p=Paragraph("", styleRegistrant)
2432            else:
2433                ids=key.split("-")
2434                if len(ids)==2:
2435                    group=self._regForm.getSectionById(ids[0])
2436                    if group is not None:
2437                        i=group.getFieldById(ids[1])
2438                        if i is not None:
2439                            p=Paragraph("""<b>%s</b>"""%escape(i.getCaption()), styleRegistrant)
2440            lp.append(p)
2441        l.append(lp)
2442
2443        if self._regList == None:
2444            self._regList = self._conf.getRegistrantsList(True)
2445        for reg in self._regList:
2446            lp = []
2447            lp.append(Paragraph("""%s"""%escape(reg.getFullName()), styleRegistrant))
2448            for key in self._display:
2449                if key == "Email":
2450                    lp.append(Paragraph("""%s"""%escape(reg.getEmail()), styleRegistrant))
2451                elif key == "Position":
2452                    lp.append(Paragraph("""%s"""%escape(reg.getPosition()), styleRegistrant))
2453                elif key == "LastName":
2454                    lp.append(Paragraph("""%s"""%escape(reg.getFamilyName()), styleRegistrant))
2455                elif key == "FirstName":
2456                    lp.append(Paragraph("""%s"""%escape(reg.getFirstName()), styleRegistrant))
2457                elif key == "Institution":
2458                    lp.append(Paragraph("""%s"""%escape(reg.getInstitution()), styleRegistrant))
2459                elif key == "Address":
2460                    lp.append(Paragraph("""%s"""%escape(reg.getAddress()), styleRegistrant))
2461                elif key == "City":
2462                    lp.append(Paragraph("""%s"""%escape(reg.getCity()), styleRegistrant))
2463                elif key == "Country":
2464                    lp.append(Paragraph("""%s"""%CountryHolder().getCountryById(reg.getCountry()), styleRegistrant))
2465                elif key == "Phone":
2466                    lp.append(Paragraph("""%s"""%escape(reg.getPhone()), styleRegistrant))
2467                elif key == "isPayed":
2468                    lp.append(Paragraph("""%s"""%escape(reg.isPayedText()), styleRegistrant))
2469                elif key == "idpayment":
2470                    lp.append(Paragraph("""%s"""%escape(reg.getIdPay()), styleRegistrant))
2471                elif key == "amountToPay":
2472                    lp.append(Paragraph("%.2f %s"%(reg.getTotal(), reg.getConference().getRegistrationForm().getCurrency()), styleRegistrant))
2473                elif key == "Sessions":
2474                    p7 = []
2475                    for ses in reg.getSessionList():
2476                        if ses is not None:
2477                            p7.append(Paragraph("""%s"""%escape(ses.getTitle()), styleRegistrant))
2478                    if p7 == []:
2479                        p7 = Paragraph("", styleRegistrant)
2480                    lp.append(p7)
2481                elif key == "SocialEvents":
2482                    p8 = []
2483                    for se in reg.getSocialEvents():
2484                        if se is not None:
2485                            p8.append(Paragraph("""%s"""%escape(se.getCaption()), styleRegistrant))
2486                    if p8 == []:
2487                        p8 = Paragraph("", styleRegistrant)
2488                    lp.append(p8)
2489                elif key == "Accommodation":
2490                    if reg.getAccommodation() is not None and reg.getAccommodation().getAccommodationType() is not None:
2491                        lp.append(Paragraph("%s"%escape(reg.getAccommodation().getAccommodationType().getCaption()), styleRegistrant))
2492                    else:
2493                        lp.append(Paragraph("", styleRegistrant))
2494                elif key == "ArrivalDate":
2495                    if reg.getAccommodation() is not None and reg.getAccommodation().getArrivalDate() is not None:
2496                        lp.append(Paragraph("%s"%escape(reg.getAccommodation().getArrivalDate().strftime("%d-%B-%Y")), styleRegistrant))
2497                    else:
2498                        lp.append(Paragraph("", styleRegistrant))
2499                elif key == "DepartureDate":
2500                    if reg.getAccommodation() is not None and reg.getAccommodation().getDepartureDate() is not None:
2501                        lp.append(Paragraph("%s"%escape(reg.getAccommodation().getDepartureDate().strftime("%d-%B-%Y")), styleRegistrant))
2502                    else:
2503                        lp.append(Paragraph("", styleRegistrant))
2504                elif key == "ReasonParticipation":
2505                    lp.append(Paragraph("""%s"""%escape(reg.getReasonParticipation() or ""), styleRegistrant))
2506                elif key == "RegistrationDate":
2507                    if reg.getRegistrationDate() is not None:
2508                        lp.append(Paragraph("""%s"""%escape(reg.getAdjustedRegistrationDate().strftime("%d-%B-%Y-%H:%M")), styleRegistrant))
2509                    else:
2510                        lp.append(Paragraph("", styleRegistrant))
2511                elif key.startswith("s-"):
2512                    ids=key.split("-")
2513                    if len(ids)==2:
2514                        status=reg.getStatusById(ids[1])
2515                        cap=""
2516                        if status.getStatusValue() is not None:
2517                            cap=status.getStatusValue().getCaption()
2518                        lp.append(Paragraph("""%s"""%escape(cap), styleRegistrant))
2519                else:
2520                    ids=key.split("-")
2521                    if len(ids)==2:
2522                        group=reg.getMiscellaneousGroupById(ids[0])
2523                        if group is not None:
2524                            i=group.getResponseItemById(ids[1])
2525                            if i is not None:
2526                                lp.append(Paragraph("""%s"""%escape(str(i.getValue())), styleRegistrant))
2527                                continue
2528                    lp.append(Paragraph("", styleRegistrant))
2529            l.append(lp)
2530        noneList = ()
2531        for i in range(0, len(self._display)+1):
2532            noneList += (None,)
2533        t=Table(l,colWidths=noneList,style=tsRegs)
2534        self._story.append(t)
2535        return story
2536
2537
2538class RegistrantsListToBadgesPDF:
2539    """
2540    Class used to print the Badges for the registrants
2541    """
2542
2543    """
2544    The following dictionary maps the names of the fonts, as returned by the javascript in WConfModifBadgeDesign.tpl,
2545    to actual TTF font names.
2546    Each font name is mapped to 4 TTF fonts: Normal one, Bold one, Italic one, Bold & Italic one.
2547    """
2548    __fonts = {'Times New Roman':['Times-Roman','Times-Bold','Times-Italic','Times-Bold-Italic'],
2549               'Courier':['Courier', 'Courier-Bold', 'Courier-Italic', 'Courier-Bold-Italic'],
2550               'OhMyGodStars':['OhMyGodStars','OhMyGodStars','OhMyGodStars','OhMyGodStars'],
2551               'OptimaThin':['Optima-Thin','Optima-Thin','Optima-Thin','Optima-Thin'],
2552               'LinuxLibertine':['LinuxLibertine','LinuxLibertine-Bold','LinuxLibertine-Italic','LinuxLibertine-Bold-Italic'],
2553               'Kochi-Mincho':['Kochi-Mincho','Kochi-Mincho','Kochi-Mincho','Kochi-Mincho'],
2554               'Kochi-Gothic':['Kochi-Gothic','Kochi-Gothic','Kochi-Gothic','Kochi-Gothic'],
2555               'Uming-CN':['Uming-CN','Uming-CN','Uming-CN','Uming-CN']
2556           #,'Bitstream Cyberbit':['Bitstream-Cyberbit', 'Bitstream-Cyberbit', 'Bitstream-Cyberbit', 'Bitstream-Cyberbit']
2557               }
2558
2559    """ The following dictionary maps the sizes of the items, as returned by the javascript in WConfModifBadgeDesign.tpl,
2560    to actual font sizes in points, as ReportLab needs.
2561    """
2562    __fontSizes = {'xx-small':9,
2563                   'x-small':10,
2564                   'small':11,
2565                   'medium':12,
2566                   'large':14,
2567                   'x-large':16,
2568                   'xx-large':24
2569                   }
2570
2571    """ The following dictionary maps the possible text alignments, as returned by the javascript in WConfModifBadgeDesign.tpl,
2572    to ReportLab constants.
2573    """
2574    __alignments = {'Left':TA_LEFT,
2575                    'Right':TA_RIGHT,
2576                    'Center':TA_CENTER,
2577                    'Justified':TA_JUSTIFY
2578                    }
2579
2580    """ The following dictionary maps the possible text colors, as returned by the javascript in WConfModifBadgeDesign.tpl,
2581    to ReportLab color constants.
2582    """
2583    __colors = {'black': colors.black,
2584                'red': colors.red,
2585                'blue': colors.blue,
2586                'green': colors.green,
2587                'yellow': colors.yellow,
2588                'brown': colors.brown,
2589                'cyan': colors.cyan,
2590                'gold': colors.gold,
2591                'pink': colors.pink,
2592                'gray': colors.gray,
2593                'white': colors.white
2594                }
2595
2596
2597    def __init__(self, conf, badgeTemplate, marginTop, marginBottom, marginLeft, marginRight, marginColumns, marginRows, pagesize, drawDashedRectangles, registrantList):
2598        """ Constructor
2599                conf: the conference for which the badges are printed, as a Conference object.
2600                badgeTemplate: the template used, as a BadgeTemplate object.
2601                marginTop: a float indicating the top margin, in cm, int or float
2602                marginBottom: a float indicating the minimum bottom margin, in cm, int or float
2603                marginLeft: a float indicating the left margin, in cm, int or float
2604                marginRight: a float indicating the minimum right margin, in cm, int or float
2605                marginColumns: a float indicating the margin between columns of badges, in cm, int or float
2606                marginRows: a float indicating the margin between rows of badges, in cm, int or float
2607                pagesize: a string with the pagesize to used, e.g. 'A4', 'A3', 'Letter'
2608                registrantList: either a string whose value should be "all", either a list of registrant id's
2609            The badges will be drawn aligned to the left.
2610        """
2611
2612        self.__conf = conf
2613        self.__badgeTemplate = badgeTemplate
2614        self.__marginTop = marginTop
2615        self.__marginBottom = marginBottom
2616        self.__marginLeft = marginLeft
2617        self.__marginRight = marginRight
2618        self.__marginColumns = marginColumns
2619        self.__marginRows = marginRows
2620
2621        if registrantList == 'all':
2622            self.__registrantList = self.__conf.getRegistrantsList(sort = True)
2623        else:
2624            self.__registrantList = [self.__conf.getRegistrantById(id) for id in registrantList]
2625
2626        self.__size = PDFSizes().PDFpagesizes[pagesize]
2627        self.__width, self.__height = self.__size
2628
2629        self.__drawDashedRectangles = drawDashedRectangles
2630
2631        setTTFonts()
2632
2633
2634    def getPDFBin(self):
2635        """ Returns the data of the PDF file to be printed
2636        """
2637
2638        self.__fileDummy = FileDummy()
2639        self.__canvas = canvas.Canvas(self.__fileDummy, pagesize = self.__size)
2640
2641        nBadgesHorizontal = int((self.__width - self.__marginLeft * cm - self.__marginRight * cm + self.__marginColumns * cm  + 0.01*cm) /
2642                                ((self.__badgeTemplate.getWidthInCm() + self.__marginColumns)  * cm))
2643
2644
2645        nBadgesVertical = int((self.__height - self.__marginTop * cm - self.__marginBottom * cm + self.__marginRows * cm + 0.01*cm) /
2646                              ((self.__badgeTemplate.getHeightInCm() + self.__marginRows) * cm))
2647
2648        # We get an instance of the position generator
2649        p = RegistrantsListToBadgesPDF.__position_generator(
2650                               nBadgesHorizontal, nBadgesVertical,
2651                               self.__badgeTemplate.getWidthInCm() * cm, self.__badgeTemplate.getHeightInCm() * cm,
2652                               self.__marginLeft * cm, self.__marginTop * cm, self.__marginColumns * cm, self.__marginRows * cm)
2653
2654        if nBadgesHorizontal == 0 or nBadgesVertical == 0:
2655            raise NoReportError( _("The template dimensions are too large for the page size you selected"))
2656
2657        # We print a badge for each registrant
2658        for registrant in self.__registrantList:
2659            try:
2660                posx, posy = p.next()
2661                self.__draw_badge(registrant, posx, posy)
2662            except StopIteration:
2663                # We have printed all the badges that fitted in 1 page, we have to restart the position generator.
2664                self.__canvas.showPage()
2665                p = RegistrantsListToBadgesPDF.__position_generator(
2666                               nBadgesHorizontal, nBadgesVertical,
2667                               self.__badgeTemplate.getWidthInCm() * cm, self.__badgeTemplate.getHeightInCm() * cm,
2668                               self.__marginLeft * cm, self.__marginTop * cm, self.__marginColumns * cm, self.__marginRows * cm)
2669                posx, posy = p.next()
2670                self.__draw_badge(registrant, posx, posy)
2671
2672        self.__canvas.save()
2673        return self.__fileDummy.getData()
2674
2675    def __position_generator(cls,
2676                             nBadgesHorizontal, nBadgesVertical,
2677                             badgeWidth, badgeHeight,
2678                             marginLeft, marginTop,
2679                             interColumnMargin, interRowMargin):
2680        """ Generates the a new position for drawing a badge each time it is called.
2681        The position of a badge is the position of the top left corner.
2682        When there are no more positions available in a page, it throws a StopIteration exception.
2683        """
2684
2685        nx = 0
2686        ny = 0
2687        while ny < nBadgesVertical:
2688            while nx < nBadgesHorizontal:
2689                x = marginLeft + nx * (badgeWidth + interColumnMargin)
2690                y = marginTop + ny * (badgeHeight + interRowMargin)
2691                nx = nx + 1
2692                yield x,y
2693            nx = 0
2694            ny = ny + 1
2695        return
2696    __position_generator = classmethod(__position_generator)
2697
2698
2699    def __draw_badge(self, registrant, posx, posy):
2700        """ Draws a badge, for a given registrant, at the position (posx, posy).
2701        (posx, posy) is the position of the top left corner of a badge.
2702        """
2703
2704        # We draw a dashed rectangle around the badge
2705        if self.__drawDashedRectangles:
2706            self.__canvas.saveState()
2707            self.__canvas.setDash(1,5)
2708            self.__canvas.rect(posx, self.__height - posy - self.__badgeTemplate.getHeightInCm() * cm,
2709                               self.__badgeTemplate.getWidthInCm() * cm, self.__badgeTemplate.getHeightInCm() * cm)
2710            self.__canvas.restoreState()
2711
2712        # We draw the background if we find it.
2713        usedBackgroundId = self.__badgeTemplate.getUsedBackgroundId()
2714        if usedBackgroundId != -1 and self.__badgeTemplate.getBackground(usedBackgroundId)[1] is not None:
2715            self.__canvas.drawImage(self.__badgeTemplate.getBackground(usedBackgroundId)[1].getFilePath(),
2716                                    posx, self.__height - posy - self.__badgeTemplate.getHeightInCm() * cm,
2717                                    self.__badgeTemplate.getWidthInCm() * cm, self.__badgeTemplate.getHeightInCm() * cm)
2718
2719
2720        # We draw the items of the badge
2721        for item in self.__badgeTemplate.getItems():
2722
2723            # First we determine the actual text that has to be drawed.
2724            action = BadgeDesignConfiguration().items_actions[item.getName()]
2725            if isinstance(action, str):
2726                # If for this kind of item we have to draw always the same string, let's draw it.
2727                text = action
2728            elif isinstance(action, types.MethodType):
2729                # If the action is a method, depending on which class owns the method, we pass a
2730                # different object to the method.
2731                if action.im_class == Registrant:
2732                    text = action.__call__(registrant)
2733                elif action.im_class == conference.Conference:
2734                    text = action.__call__(self.__conf)
2735                elif action.im_class == BadgeTemplateItem:
2736                    text = action.__call__(item)
2737                else:
2738                    text= _("Error")
2739            elif isinstance(action, types.ClassType):
2740                # If the action is a class, it must be a class who complies to the following interface:
2741                #  -it must have a getArgumentType() method, which returns either Conference, Registrant or BadgeTemplateItem.
2742                #  Depending on what is returned, we will pass a different object to the getValue() method.
2743                #  -it must have a getValue(object) method, to which a Conference instance, a Registrant instance or a
2744                #  BadgeTemplateItem instance must be passed, depending on the result of the getArgumentType() method.
2745                argumentType = action.getArgumentType()
2746                if argumentType == Registrant:
2747                    text = action.getValue(registrant)
2748                elif argumentType == conference.Conference:
2749                    text = action.getValue(self.__conf)
2750                elif argumentType == BadgeTemplateItem:
2751                    text = action.getValue(item)
2752                else:
2753                    text = _("Error")
2754            else:
2755                text = _("Error")
2756
2757            if not isinstance(text, basestring):
2758                text = str(text)
2759            text = escape(text)
2760
2761            #style definition for the Paragraph used to draw the text.
2762            style = ParagraphStyle({})
2763            style.alignment = RegistrantsListToBadgesPDF.__alignments[item.getTextAlign()]
2764            style.textColor = RegistrantsListToBadgesPDF.__colors[item.getColor()]
2765            style.fontSize = RegistrantsListToBadgesPDF.__fontSizes[item.getFontSize()]
2766            style.leading = style.fontSize
2767
2768            if item.isBold() and item.isItalic():
2769                style.fontName = style.fontName = RegistrantsListToBadgesPDF.__fonts[item.getFont()][3]
2770            elif item.isItalic():
2771                style.fontName = style.fontName = RegistrantsListToBadgesPDF.__fonts[item.getFont()][2]
2772            elif item.isBold():
2773                style.fontName = style.fontName = RegistrantsListToBadgesPDF.__fonts[item.getFont()][1]
2774            else:
2775                style.fontName = style.fontName = RegistrantsListToBadgesPDF.__fonts[item.getFont()][0]
2776
2777            p = Paragraph(text, style)
2778
2779            itemx = self.__badgeTemplate.pixelsToCm(item.getX()) * cm
2780            itemy = self.__badgeTemplate.pixelsToCm(item.getY()) * cm
2781
2782            availableWidth = self.__badgeTemplate.pixelsToCm(item.getWidth()) * cm
2783            availableHeight = (self.__badgeTemplate.getHeightInCm()
2784                               - self.__badgeTemplate.pixelsToCm(item.getY()) \
2785                              ) * cm
2786
2787            w,h = p.wrap(availableWidth, availableHeight)
2788
2789            if w > availableWidth or h > availableHeight:
2790                ## TODO: give warnings
2791                pass
2792
2793            p.drawOn(self.__canvas, posx + itemx, self.__height - posy - itemy - h)
2794
2795
2796class LectureToPosterPDF:
2797    """
2798    Class used to print a lecture's poster
2799    """
2800
2801    """ The following dictionary maps the names of the fonts, as returned by the javascript in WConfModifPosterDesign.tpl,
2802    to actual TTF font names.
2803    Each font name is mapped to 4 TTF fonts: Normal one, Bold one, Italic one, Bold & Italic one.
2804    """
2805    __fonts = {'Times New Roman':['Times-Roman','Times-Bold','Times-Italic','Times-Bold-Italic'],
2806               'Courier':['Courier', 'Courier-Bold', 'Courier-Italic', 'Courier-Bold-Italic'],
2807               'OhMyGodStars':['OhMyGodStars','OhMyGodStars','OhMyGodStars','OhMyGodStars'],
2808               'OptimaThin':['Optima-Thin','Optima-Thin','Optima-Thin','Optima-Thin'],
2809               'LinuxLibertine':['LinuxLibertine','LinuxLibertine-Bold','LinuxLibertine-Italic','LinuxLibertine-Bold-Italic'],
2810               'Kochi-Mincho':['Kochi-Mincho','Kochi-Mincho','Kochi-Mincho','Kochi-Mincho'],
2811               'Kochi-Gothic':['Kochi-Gothic','Kochi-Gothic','Kochi-Gothic','Kochi-Gothic'],
2812               'Uming-CN':['Uming-CN','Uming-CN','Uming-CN','Uming-CN']
2813           #,'Bitstream Cyberbit':['Bitstream-Cyberbit', 'Bitstream-Cyberbit', 'Bitstream-Cyberbit', 'Bitstream-Cyberbit']
2814               }
2815
2816
2817    """ The following dictionary maps the possible text alignments, as returned by the javascript in WConfModifPosterDesign.tpl,
2818    to ReportLab constants.
2819    """
2820    __alignments = {'Left':TA_LEFT,
2821                    'Right':TA_RIGHT,
2822                    'Center':TA_CENTER,
2823                    'Justified':TA_JUSTIFY
2824                    }
2825
2826    """ The following dictionary maps the possible text colors, as returned by the javascript in WConfModifPosterDesign.tpl,
2827    to ReportLab color constants.
2828    """
2829    __colors = {'black': colors.black,
2830                'red': colors.red,
2831                'blue': colors.blue,
2832                'green': colors.green,
2833                'yellow': colors.yellow,
2834                'brown': colors.brown,
2835                'cyan': colors.cyan,
2836                'gold': colors.gold,
2837                'pink': colors.pink,
2838                'gray': colors.gray,
2839                'white': colors.white
2840                }
2841
2842
2843    def __init__(self, conf, posterTemplate, marginH, marginV, pagesize, tz=None):
2844        """ Constructor
2845        conf: the conference for which the posters are printed, as a Conference object.
2846        posterTemplate: the template used, as a PosterTemplate object.
2847        marginH: a number indicating the minimal horizontal margin
2848        marginV: a number indicating the minimal vertical margin
2849        pagesize: a string with the pagesize to used, e.g. 'A4', 'A3', 'Letter'
2850        registrantList: either a string whose value should be "all",
2851                        either a list of registrant id's
2852        """
2853
2854        self.__conf = conf
2855        if not tz:
2856            self._tz = self.__conf.getTimezone()
2857        else:
2858            self._tz = tz
2859        self.__posterTemplate = posterTemplate
2860        self.__marginH = marginH
2861        self.__marginV = marginV
2862
2863        self.__size = PDFSizes().PDFpagesizes[pagesize]
2864        self.__width, self.__height = self.__size
2865
2866        setTTFonts()
2867
2868    """ The following function maps the sizes of the items, as returned by the javascript in WConfModifPosterDesign.tpl,
2869    to actual font sizes in points, as ReportLab needs.
2870    """
2871    def __extract_size(cls, sizePt):
2872
2873        m = re.match(r"(\d+)(pt)",sizePt)
2874
2875        if m:
2876            return int(m.group(1))
2877        return None
2878    __extract_size = classmethod (__extract_size)
2879
2880
2881    def getPDFBin(self):
2882        """ Returns the data of the PDF file to be printed
2883        """
2884
2885        self.__fileDummy = FileDummy()
2886        self.__canvas = canvas.Canvas(self.__fileDummy, pagesize = self.__size)
2887
2888        self.__draw_poster(self.__marginH * cm, self.__marginV * cm)
2889
2890        self.__canvas.save()
2891        return self.__fileDummy.getData()
2892
2893    def __draw_background(self, file, position, posx, posy):
2894
2895        img = Image.open(file)
2896
2897        imgWidth, imgHeight = img.size
2898
2899        posx = self.__posterTemplate.pixelsToCm(posx);
2900        posy = self.__posterTemplate.pixelsToCm(posy);
2901
2902        if position == "Stretch":
2903            x_1 = posx
2904            y_1 = posy
2905            width = self.__posterTemplate.getWidthInCm()
2906            height = self.__posterTemplate.getHeightInCm()
2907
2908        elif position == "Center":
2909            height = self.__posterTemplate.pixelsToCm(imgHeight)
2910            width = self.__posterTemplate.pixelsToCm(imgWidth)
2911
2912            posterWidth = self.__posterTemplate.getWidthInCm()
2913            posterHeight = self.__posterTemplate.getHeightInCm()
2914
2915            if width > posterWidth or height > posterHeight:
2916
2917                if width > posterWidth:
2918                    ratio = float(posterWidth)/width;
2919                    width = posterWidth;
2920                    height = height*ratio
2921
2922                    x_1 = posx;
2923                    y_1 = posy + (posterHeight - height)/2.0;
2924
2925
2926                if  height > posterHeight:
2927                    ratio = float(posterHeight)/height;
2928                    height = posterHeight;
2929                    width = width*ratio
2930                    x_1 = posx + (posterWidth - width)/2.0;
2931                    y_1 = posy;
2932            else:
2933                x_1 = posx + (posterWidth - self.__posterTemplate.pixelsToCm(imgWidth))/2.0
2934                y_1 = posy + (posterHeight - self.__posterTemplate.pixelsToCm(imgHeight))/2.0
2935
2936        self.__canvas.drawImage(file,
2937             x_1 * cm, y_1 * cm,
2938             width * cm, height * cm)
2939
2940
2941    def __draw_poster(self, posx, posy):
2942        """ Draws a poster, for a given registrant, at the position (posx, posy).
2943        (posx, posy) is the position of the top left corner of a poster.
2944        """
2945
2946        # We draw the background if we find it.
2947        usedBackgroundId = self.__posterTemplate.getUsedBackgroundId()
2948
2949        if usedBackgroundId != -1 and self.__posterTemplate.getBackground(usedBackgroundId)[1] is not None:
2950
2951            self.__draw_background(self.__posterTemplate.getBackground(usedBackgroundId)[1].getFilePath(),
2952                             self.__posterTemplate.getBackgroundPosition(usedBackgroundId),posx,posy)
2953
2954        # We draw the items of the poster
2955        for item in self.__posterTemplate.getItems():
2956
2957            # First we determine the actual text that has to be drawed.
2958            action = PosterDesignConfiguration().items_actions[item.getName()]
2959
2960            if isinstance(action, str):
2961                # If for this kind of item we have to draw always the same string, let's draw it.
2962                # text is passed in lists, because some fields need several lines
2963                text = [action]
2964            elif isinstance(action, types.MethodType):
2965                # If the action is a method, depending on which class owns the method, we pass a
2966                # different object to the method.
2967                if action.im_class == conference.Conference:
2968                    text = action.__call__(self.__conf).replace("\r\n","\n").split("\n")
2969                elif action.im_class == PosterTemplateItem:
2970                    text = [action.__call__(item)]
2971                else:
2972                    text= [_("Error")]
2973            elif isinstance(action, types.ClassType):
2974                # If the action is a class, it must be a class who complies to the following interface:
2975                #  -it must have a getArgumentType() method, which returns either Conference or PosterTemplateItem.
2976                #  Depending on what is returned, we will pass a different object to the getValue() method.
2977                #  -it must have a getValue(object) method, to which a Conference instance or a
2978                #  PosterTemplateItem instance must be passed, depending on the result of the getArgumentType() method.
2979                argumentType = action.getArgumentType()
2980                if action.__name__ == "ConferenceChairperson":
2981                    #this specific case may need more than one line
2982                    chairList = action.getValue(self.__conf)
2983
2984                    # 'text' is a list of lines
2985                    text = []
2986                    # let's fill it with the chairpersons' names
2987                    for chair in chairList:
2988                        if chair.getAffiliation() != "":
2989                            text.append("%s (%s)" % (chair.getDirectFullName(),chair.getAffiliation()))
2990                        else:
2991                            text.append(chair.getDirectFullName())
2992
2993                elif argumentType == conference.Conference:
2994                    text = [action.getValue(self.__conf)]
2995                elif argumentType == PosterTemplateItem:
2996                    text = [action.getValue(item)]
2997                else:
2998                    text = [_("Error")]
2999            else:
3000                text = [_("Error")]
3001
3002            text = map(escape,text)
3003
3004            #style definition for the Paragraph used to draw the text.
3005            style = ParagraphStyle({})
3006            style.alignment = LectureToPosterPDF.__alignments[item.getTextAlign()]
3007            style.textColor = LectureToPosterPDF.__colors[item.getColor()]
3008            style.fontSize = LectureToPosterPDF.__extract_size(item.getFontSize())
3009            style.leading = style.fontSize
3010
3011            if item.isBold() and item.isItalic():
3012                style.fontName = style.fontName = LectureToPosterPDF.__fonts[item.getFont()][3]
3013            elif item.isItalic():
3014                style.fontName = style.fontName = LectureToPosterPDF.__fonts[item.getFont()][2]
3015            elif item.isBold():
3016                style.fontName = style.fontName = LectureToPosterPDF.__fonts[item.getFont()][1]
3017            else:
3018                style.fontName = style.fontName = LectureToPosterPDF.__fonts[item.getFont()][0]
3019
3020            availableWidth = self.__posterTemplate.pixelsToCm(item.getWidth()) * cm
3021            availableHeight = (self.__posterTemplate.getHeightInCm()
3022                               - self.__posterTemplate.pixelsToCm(item.getY()) \
3023                              ) * cm
3024
3025            w,h = 0,0
3026            itemx = self.__posterTemplate.pixelsToCm(item.getX()) * cm
3027            itemy = self.__posterTemplate.pixelsToCm(item.getY()) * cm
3028
3029            # now, we iterate over the line set
3030            for line in text:
3031                if line == "":
3032                    itemy += style.fontSize
3033                else:
3034                    p = Paragraph(line, style)
3035
3036                    itemy += h
3037
3038                    w,h = p.wrap(availableWidth, availableHeight)
3039
3040                    if w > availableWidth or h > availableHeight:
3041                        ## TODO: warnings
3042                        pass
3043
3044                    # finally, draw
3045                    p.drawOn(self.__canvas, posx + itemx, self.__height - posy - itemy - h)
Note: See TracBrowser for help on using the repository browser.