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.

Location:
main/waeup.kofa/trunk/src/waeup/kofa
Files:
2 edited

Legend:

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

    r8059 r8091  
    5656            ar_translation, self.context.application_number)
    5757
    58     def _setUpWidgets(self):
    59         """Setup simple display widgets.
    60 
    61         Returns the list of widgets.
    62         """
    63         request = TestRequest()
    64         return setUpEditWidgets(
    65             self.form_fields, 'form', self.context, request, {},
    66             for_display=True, ignore_request=True
    67             )
    68 
    6958    def _getCourseAdmittedLink(self, view):
    7059        """Return link, title and code in html format to the certificate
     
    7968        return ''
    8069
    81     def _addPassportImage(self, data):
    82         """Add passport image to data stream.
     70    def _getDeptAndFaculty(self):
     71        """Return long titles of department and faculty.
    8372
    84         If no image exists yet the default image is added.
     73        Returns a list [department_title, faculty_title]
     74
     75        If the context applicant has no course admitted or dept. and
     76        faculty cannot be determined, ``None`` is returned.
    8577        """
    86         img = getUtility(IExtFileStore).getFileByContext(self.context)
    87         if img is None:
    88             img = open(DEFAULT_PASSPORT_IMAGE_PATH, 'rb')
    89         doc_img = Image(img.name, width=4*cm, height=3*cm, kind='bound')
    90         data.append([doc_img])
    91         data.append([Spacer(1, 18)])
    92         return data
    93 
    94     def _addDeptAndFaculty(self, data):
    95         """If we have a valid course admitted, add dept. and faculty to data
    96            stream.
    97         """
    98         style = getSampleStyleSheet()
    9978        course_admitted = self.context.course_admitted
    10079        dept = getattr(
    10180                getattr(course_admitted, '__parent__', None),
    10281                '__parent__', None)
    103         if dept is None:
    104             return data
    105         portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
    106         dp_translation = translate(_('Department:'),
    107             'waeup.kofa', target_language=portal_language)
    108         f_label = '<font size=12>%s</font>' % dp_translation
    109         f_text = '<font size=12>%s</font>' % dept.longtitle()
    110         f_label = Paragraph(f_label, style["Normal"])
    111         f_text = Paragraph(f_text, style["Normal"])
    112         data.append([f_label,f_text])
    113 
    11482        faculty = getattr(dept, '__parent__', None)
    115         if faculty is None:
    116             return data
    117         fc_translation = translate(_('Faculty:'),
    118             'waeup.kofa', target_language=portal_language)
    119         f_label = '<font size=12>%s</font>' % fc_translation
    120         f_text = '<font size=12>%s</font>' % faculty.longtitle()
    121         f_label = Paragraph(f_label, style["Normal"])
    122         f_text = Paragraph(f_text, style["Normal"])
    123         data.append([f_label,f_text])
    124         return data
    125 
    126     def _getWidgetsTable(self, view):
    127         """Return a reportlab table buildt of widgets.
    128         """
    129         style = getSampleStyleSheet()
    130         table_data = []
    131         table_style = [('LEFTPADDING', (0,0), (0,-1), 0),
    132                        ('VALIGN', (0,0), (-1,-1), 'TOP'),
    133                        ]
    134         row_num = 0
    135         widgets = self._setUpWidgets()
    136         portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
    137         for widget in widgets:
    138             separators = getUtility(IApplicantsUtils).SEPARATORS_DICT
    139             if separators and separators.get(widget.name):
    140                 f_headline = ('<font size=12><strong>%s</strong></font>'
    141                     % translate(separators[widget.name], 'waeup.kofa',
    142                     target_language=portal_language))
    143                 f_headline = Paragraph(f_headline, style["Normal"])
    144                 table_data.append([f_headline ])
    145                 table_style.append(('SPAN', (0,row_num), (-1,row_num)),)
    146                 table_style.append(
    147                     ('TOPPADDING', (0,row_num), (-1,row_num), 12),)
    148                 row_num += 1
    149             f_label = '<font size=12>%s</font>:' % translate(
    150                 widget.label.strip(), 'waeup.kofa',
    151                 target_language=portal_language)
    152             f_label = Paragraph(f_label, style["Normal"])
    153             f_text = '<font size=12>%s</font>' % widget()
    154             # Add br tag if widgets contain div tags
    155             # which are not supported by reportlab
    156             f_text = f_text.replace('</div>', '</div><br />')
    157             f_text = f_text.replace('\n', '')
    158             f_text = Paragraph(f_text, style["Normal"])
    159             table_data.append([f_label,f_text])
    160             row_num += 1
    161         adm_translation = translate(_('Admitted Course of Study:'),
    162                 'waeup.kofa', target_language=portal_language)
    163         f_label = '<font size=12>%s</font>' % adm_translation
    164         f_text = '<font size=12>%s</font>' % (
    165             self._getCourseAdmittedLink(view),)
    166         f_label = Paragraph(f_label, style["Normal"])
    167         f_text = Paragraph(f_text, style["Normal"])
    168         table_data.append([f_label,f_text])
    169         row_num += 1
    170 
    171         # Add dept. and faculty if applicable
    172         table_data = self._addDeptAndFaculty(table_data)
    173 
    174         # Create table
    175         table = Table(table_data,style=table_style)
    176         table.hAlign = 'LEFT'
    177         return table
     83        return [x is not None and x.longtitle() or x for x in dept, faculty]
    17884
    17985    def _addComments(self, data):
     
    205111        principal.
    206112        """
    207         doc_title = self.title.replace('-', '\n')
     113        doc_title = '\n'.join([x.strip() for x in self.title.split('-')])
    208114        style = getSampleStyleSheet()
    209115        data = []
     116        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
     117        separators = getUtility(IApplicantsUtils).SEPARATORS_DICT
     118        creator = getUtility(IPDFCreator)
    210119
    211120        # append history
    212         for msg in self.context.history.messages:
    213             f_msg = '<font face="Courier" size=10>%s</font>' % msg
    214             data.append(Paragraph(f_msg, style["Normal"]))
    215         data.append(Spacer(1, 20))
     121        data.extend(creator.fromStringList(self.context.history.messages))
    216122
    217123        # append photograph
     
    219125            getUtility(IExtFileStore).getFileByContext(self.context),
    220126            'name', DEFAULT_PASSPORT_IMAGE_PATH)
    221         doc_img = Image(img_path, width=4*cm, height=3*cm, kind='bound')
    222         doc_img.hAlign='LEFT'
    223         data.append(doc_img)
     127        data.append(creator.getImage(img_path))
     128        data.append(Spacer(1, 12))
    224129
    225130        # append widgets
    226         data.append(self._getWidgetsTable(view))
     131        dept, faculty = self._getDeptAndFaculty()
     132        data.append(creator.getWidgetsTable(
     133            self.form_fields, self.context, view, lang=portal_language,
     134            domain='waeup.kofa', separators=separators,
     135            course_label='Admitted Course of Study:',
     136            course_link=self._getCourseAdmittedLink(view),
     137            dept=dept, faculty=faculty))
    227138
    228139        # append comments
    229140        data = self._addComments(data)
    230 
    231         creator = getUtility(IPDFCreator)
    232141        return creator.create_pdf(data, None, doc_title)
  • 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.