Ignore:
Timestamp:
10 Apr 2012, 10:43:50 (12 years ago)
Author:
uli
Message:

Move lots of reusable code from applicant pdf slip into global pdf creator.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/browser/pdf.py

    r8089 r8091  
    2525from reportlab.lib.units import cm, inch
    2626from reportlab.lib.pagesizes import A4, landscape, portrait
    27 from reportlab.platypus import SimpleDocTemplate
     27from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
     28from reportlab.platypus import (
     29    SimpleDocTemplate, Spacer, Paragraph, Image, Table)
     30from zope.component import getUtility
     31from zope.formlib.form import setUpEditWidgets
     32from zope.i18n import translate
     33from zope.publisher.browser import TestRequest
    2834from waeup.kofa.browser.interfaces import IPDFCreator
     35from waeup.kofa.interfaces import MessageFactory as _
     36
     37#: A reportlab paragraph style for 'normal' output.
     38NORMAL_STYLE = getSampleStyleSheet()['Normal']
     39
     40#: A reportlab paragraph style for output of 'code'.
     41CODE_STYLE = ParagraphStyle(
     42    name='Code',
     43    parent=NORMAL_STYLE,
     44    fontName='Courier',
     45    fontSize=10,
     46    )
     47
     48#: A reportlab paragraph style for regular form output.
     49ENTRY1_STYLE = ParagraphStyle(
     50    name='Entry1',
     51    parent=NORMAL_STYLE,
     52    fontSize=12,
     53    )
     54
     55#: A reportlab paragraph style for headlines or bold text in form output.
     56HEADLINE1_STYLE = ParagraphStyle(
     57    name='Header1',
     58    parent=NORMAL_STYLE,
     59    fontName='Helvetica-Bold',
     60    fontSize=12,
     61    )
     62
     63def format_html(html):
     64    """Make HTML code usable for use in reportlab paragraphs.
     65
     66    Main things fixed here:
     67
     68    - remove newlines (not visible in HTML but visible in PDF)
     69    - add <br> tags after <div> (as divs break lines in HTML but not in PDF)
     70    """
     71    # Add br tag if widgets contain div tags
     72    # which are not supported by reportlab
     73    html = html.replace('</div>', '</div><br />')
     74    html = html.replace('\n', '')
     75    return html
    2976
    3077class PDFCreator(grok.GlobalUtility):
     78    """A utility to help with generating PDF docs.
     79    """
    3180    grok.implements(IPDFCreator)
    3281
     
    3584    watermark_path = os.path.join(
    3685        os.path.dirname(__file__), 'static', 'pdf_watermark.jpg')
     86
     87    @classmethod
     88    def _setUpWidgets(cls, form_fields, context):
     89        """Setup simple display widgets.
     90
     91        Returns the list of widgets.
     92        """
     93        request = TestRequest()
     94        return setUpEditWidgets(
     95            form_fields, 'form', context, request, {},
     96            for_display=True, ignore_request=True
     97            )
     98
     99    @classmethod
     100    def _addCourse(cls, table_data, row_num, course_label, course_link,
     101                   lang, domain):
     102        """Add course data to `table_data`.
     103        """
     104        if not course_label or not course_link:
     105            return table_data, row_num
     106        f_label= translate(
     107            _(course_label), domain, target_language=lang)
     108        f_label = Paragraph(f_label, ENTRY1_STYLE)
     109        f_text = Paragraph(course_link, ENTRY1_STYLE)
     110        table_data.append([f_label, f_text])
     111        row_num += 1
     112        return table_data, row_num
     113
     114    @classmethod
     115    def _addDeptAndFaculty(cls, table_data, row_num, dept, faculty,
     116                           lang, domain):
     117        """Add `dept` and `faculty` as table rows to `table_data`.
     118
     119        `dept` and `faculty` are expected to be strings or None. In
     120        latter case they are not put into the table.
     121        """
     122        for label, text in (('Department:', dept), ('Faculty:', faculty)):
     123            if text is None:
     124                continue
     125            label = translate(_(label), domain, target_language=lang)
     126            table_data.append([
     127                Paragraph(label, ENTRY1_STYLE),
     128                Paragraph(text, ENTRY1_STYLE)])
     129            row_num += 1
     130        return table_data, row_num
     131
     132    @classmethod
     133    def fromStringList(cls, string_list):
     134        """Generate a list of reportlab paragraphs out of a list of strings.
     135
     136        Strings are formatted with :data:`CODE_STYLE` and a spacer is
     137        appended at end.
     138        """
     139        result = []
     140        for msg in string_list:
     141            result.append(Paragraph(msg, CODE_STYLE))
     142        result.append(Spacer(1, 20))
     143        return result
     144
     145    @classmethod
     146    def getImage(cls, image_path, orientation='LEFT'):
     147        """Get an image located at `image_path` as reportlab flowable.
     148        """
     149        img = Image(image_path, width=4*cm, height=3*cm, kind='bound')
     150        img.hAlign=orientation
     151        return img
     152
     153    def getWidgetsTable(self, form_fields, context, view, lang='en',
     154                        domain='waeup.kofa', separators=None,
     155                        course_label=None, course_link=None, dept=None,
     156                        faculty=None):
     157        """Return a reportlab `Table` instance, created from widgets
     158        determined by `form_fields` and `context`.
     159
     160        - `form_fields`
     161           is a list of schema fields as created by grok.AutoFields.
     162        - `context`
     163           is some object whose content is rendered here.
     164        - `view`
     165           is currently not used but supposed to be a view which is
     166           actually rendering a PDF document.
     167        - `lang`
     168           the portal language. Used for translations of strings.
     169        - `domain`
     170           the translation domain used for translations of strings.
     171        - `separators`
     172           a list of separators.
     173        - `course_label` and `course_link`
     174           if a course should be added to the table, `course_label`
     175           and `course_link` can be given, both being strings. They
     176           will be rendered in an extra-row.
     177        - `dept` and `faculty`
     178           if these are given, we render extra rows with faculty and
     179           department.
     180        """
     181        style = getSampleStyleSheet()
     182        table_data = []
     183        table_style = [('LEFTPADDING', (0,0), (0,-1), 0),
     184                       ('VALIGN', (0,0), (-1,-1), 'TOP'),
     185                       ]
     186        row_num = 0
     187        widgets = self._setUpWidgets(form_fields, context)
     188        for widget in widgets:
     189            if separators and separators.get(widget.name):
     190                f_headline = translate(
     191                    separators[widget.name], domain, target_language=lang)
     192                f_headline = Paragraph(f_headline, HEADLINE1_STYLE)
     193                table_data.append([f_headline ])
     194                table_style.append(('SPAN', (0,row_num), (-1,row_num)),)
     195                table_style.append(
     196                    ('TOPPADDING', (0,row_num), (-1,row_num), 12),)
     197                row_num += 1
     198            f_label = translate(widget.label.strip(), domain,
     199                                target_language=lang)
     200            f_label = Paragraph(f_label, ENTRY1_STYLE)
     201            f_text = format_html(widget())
     202            f_text = Paragraph(f_text, ENTRY1_STYLE)
     203            table_data.append([f_label,f_text])
     204            row_num += 1
     205
     206        # Add course (admitted, etc.) if applicable
     207        table_data, row_num = self._addCourse(
     208            table_data, row_num, course_label, course_link, lang, domain,)
     209
     210        ## Add dept. and faculty if applicable
     211        table_data, row_num = self._addDeptAndFaculty(
     212            table_data, row_num, dept, faculty, lang, domain)
     213
     214        # Create table
     215        table = Table(table_data,style=table_style)
     216        table.hAlign = 'LEFT'
     217        return table
     218
    37219
    38220    def paint_background(self, canvas, doc):
     
    61243        # Header
    62244        head_title = getattr(
    63             doc, 'kofa_headtitle', getattr(grok.getSite()['configuration'], 'name',
    64                                            u'Sample University'))
     245            doc, 'kofa_headtitle', getattr(
     246                grok.getSite()['configuration'], 'name',
     247                u'Sample University'))
    65248        canvas.setFont("Helvetica-Bold", 18)
    66249        canvas.drawString(1.5*cm, height-1.7*cm, head_title)
Note: See TracChangeset for help on using the changeset viewer.