Example #1
0
    def __call__(self,
                 record=None,
                 filepath=None,
                 folder=None,
                 filename=None,
                 hideTemplate=False,
                 rebuild=True,
                 htmlContent=None,
                 page_debug=None,
                 is_draft=None,
                 **kwargs):
        """Return the html corresponding to a given record. The html can be loaded from
        a cached document or created as new if still doesn't exist"""
        if record is None:
            record = Bag()
        self.htmlContent = htmlContent
        self._data = Bag()
        self.is_draft = is_draft
        self.record = record
        self.setData('record', record)  #compatibility
        for k, v in kwargs.items():
            self.setData(k, v)
        if not filepath:
            folder = folder or tempfile.mkdtemp()
            filepath = os.path.join(folder, filename
                                    or self.outputDocName(ext='html'))
        self.filepath = filepath
        if not rebuild:
            with open(self.filepath, 'r') as f:
                result = f.read()
            return result

        self.templates = kwargs.pop('templates', self.templates)
        self.letterhead_id = kwargs.pop('letterhead_id', self.letterhead_id)
        self.print_button = kwargs.pop('print_button', self.print_button)
        if self.onRecordLoaded() is False:
            return False

        self.showTemplate(hideTemplate is not True)
        self.htmlTemplate = None
        self.prepareTemplates()
        self.page_debug = page_debug or self.page_debug
        self.builder = GnrHtmlBuilder(
            page_width=self.page_width,
            page_height=self.page_height,
            page_margin_top=self.page_margin_top,
            page_margin_bottom=self.page_margin_bottom,
            page_margin_left=self.page_margin_left,
            page_margin_right=self.page_margin_right,
            page_debug=self.page_debug,
            print_button=self.print_button,
            htmlTemplate=self.htmlTemplate,
            css_requires=self.get_css_requires(),
            showTemplateContent=self.showTemplateContent,
            parent=self)
        result = self.createHtml(filepath=self.filepath,
                                 body_attributes=self.body_attributes)
        return result
Example #2
0
 def init(self, **kwargs):
     self.maintable = self.maintable or self.resource_table
     self.maintable_obj = self.db.table(self.maintable)
     if self.templates:
         self.htmlTemplate = self.db.table('adm.htmltemplate').getTemplate(self.templates)
     self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                   page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                   page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                   page_debug=self.page_debug, print_button=self.print_button,
                                   htmlTemplate=self.htmlTemplate)
Example #3
0
    def __call__(self, record=None, filepath=None,
                 rebuild=False, dontSave=False, pdf=False, runKwargs=None,
                 showTemplateContent=None, **kwargs):
        """This method returns the html corresponding to a given record.
           the html can be loaded from a cached document or created if still doesn't exist.
        """
        if not record:
            return False
        self.showTemplateContent = showTemplateContent or True
        loadResult = self.loadRecord(record, **kwargs)
        if loadResult == False:
            return False
        self.htmlTemplate = None
        if self.templates:
            self.htmlTemplate = self.db.table('adm.htmltemplate').getTemplate(self.templates)
            self.page_height = self.page_height or self.htmlTemplate['main.page.height'] or 280
            self.page_width = self.page_width or self.htmlTemplate['main.page.width'] or 200
            self.page_header_height = self.page_header_height or  self.htmlTemplate['layout.top?height'] or 0
            self.page_footer_height = self.page_footer_height or  self.htmlTemplate['layout.bottom?height'] or 0
            self.page_leftbar_width = self.page_leftbar_width or  self.htmlTemplate['layout.left?width'] or 0
            self.page_rightbar_width = self.page_leftbar_width or  self.htmlTemplate['layout.right?width'] or 0
            self.page_margin_top = self.page_margin_top or self.htmlTemplate['main.page.top'] or 0
            self.page_margin_left = self.page_margin_left or self.htmlTemplate['main.page.left'] or 0
            self.page_margin_right = self.page_margin_right or self.htmlTemplate['main.page.right'] or 0
            self.page_margin_bottom = self.page_margin_bottom or self.htmlTemplate['main.page.bottom'] or 0

        self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                      page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                      page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                      page_debug=self.page_debug, print_button=self.print_button,
                                      htmlTemplate=self.htmlTemplate,
                                      showTemplateContent=self.showTemplateContent)
        #if not (dontSave or pdf):
        self.filepath = filepath or os.path.join(self.hmtlFolderPath(), self.outputDocName(ext='html'))
        #else:
        #    self.filepath = None
        # 
        if self.page_height<self.page_width:
            self.orientation='Landscape'
        else:
            self.orientation='Portrait'
        if rebuild or not os.path.isfile(self.filepath):
            html = self.createHtml(filepath=self.filepath, **kwargs)

        else:
            with open(self.filepath, 'r') as f:
                html = f.read()
        if pdf:
            temp = tempfile.NamedTemporaryFile(suffix='.pdf')
            self.page.getService('print').htmlToPdf(self.filepath, temp.name, orientation=self.orientation)
            with open(temp.name, 'rb') as f:
                html = f.read()
        self.onRecordExit(self.getData('record'))
        return html
Example #4
0
 def init(self, **kwargs):
     self.maintable = self.maintable or self.resource_table
     self.maintable_obj = self.db.table(self.maintable)
     if self.templates:
         self.htmlTemplate = self.db.table('adm.htmltemplate').getTemplate(self.templates)
     self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                   page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                   page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                   page_debug=self.page_debug, print_button=self.print_button,
                                   htmlTemplate=self.htmlTemplate)
Example #5
0
    def getHtmlBuilder(self,letterhead_pkeys=None):
        """Prepare the layout template
        
        :param tpl: the template"""
        
        letterhead_pkeys = letterhead_pkeys.split(',') if isinstance(letterhead_pkeys,basestring) else letterhead_pkeys
        first_letterhead = letterhead_pkeys[0]
        f = self.query(where='$id IN :pk',pk=letterhead_pkeys,bagFields=True).fetchAsDict('id')
        first_letterhead_record = f[first_letterhead]
        if len(letterhead_pkeys) == 1 and first_letterhead_record['based_on']:
            return self.getHtmlBuilder(self.letterheadChain(first_letterhead))
        base_letterhead_bag = Bag()
        base_letterhead_bag.setItem('layer_0',Bag(first_letterhead_record['data']))
        builder = GnrHtmlBuilder(htmlTemplate=base_letterhead_bag)
        builder.initializeSrc()
        height=builder.page_height - builder.page_margin_top - builder.page_margin_bottom
        width=builder.page_width - builder.page_margin_left - builder.page_margin_right
       #page = builder.body.div(height='%imm' %builder.page_height,width='%imm' %builder.page_width,
       #                        position='relative',_class='letterhead_page')

        page = builder.body.div(style="""position:relative;
                                   width:%smm;
                                   height:%smm;
                                   top:0mm;
                                   left:0mm;
                                   """ % (builder.page_width, builder.page_height),
                                   _class='letterhead_page')


        builder.letterhead_root = page.div(style="""position:absolute;
                                   top:%imm;
                                   left:%imm;
                                   right:%imm;
                                   bottom:%imm;""" % (
                            builder.page_margin_top, builder.page_margin_left,
                            builder.page_margin_right, builder.page_margin_bottom))

        for i,pkey in enumerate(letterhead_pkeys):
            regions = self.letterhead_layer(builder, Bag(f[pkey]['data']),width=width,height=height,count=i)
        builder._regions = regions
        regions['center_center'].attributes['content_node'] ='t'
        return builder
Example #6
0
 def print_tutorial_content(self,record_id=None,**kwargs):
     builder = GnrHtmlBuilder(page_height=297, page_width=21, page_margin_top=5,
                          page_margin_left=5)
     builder.initializeSrc()
     builder.styleForLayout()
     data = Bag()
     if self.print_table:
         if self.record_mode:
             if record_id:
                 data = self.db.table(self.print_table).record(pkey=record_id).output('bag')
         else:
             data = self.db.table(self.print_table).query().selection().output('records')
     self.printContent(builder.body,data=data)
     result = Bag()
     result['htmlsource'] = builder.toHtml()
     builder.toPdf(self.site.getStaticPath('page:testpdf','preview.pdf',autocreate=-1))
     result['pdfsrc'] = self.site.getStaticUrl('page:testpdf','preview.pdf')
     return result
Example #7
0
    def getHtmlBuilder(self, letterhead_pkeys=None):
        """Prepare the layout template
        
        :param tpl: the template"""

        letterhead_pkeys = letterhead_pkeys.split(',') if isinstance(
            letterhead_pkeys, basestring) else letterhead_pkeys
        first_letterhead = letterhead_pkeys[0]
        f = self.query(where='$id IN :pk', pk=letterhead_pkeys,
                       bagFields=True).fetchAsDict('id')
        first_letterhead_record = f[first_letterhead]
        if len(letterhead_pkeys) == 1 and first_letterhead_record['based_on']:
            return self.getHtmlBuilder(self.letterheadChain(first_letterhead))
        base_letterhead_bag = Bag()
        base_letterhead_bag.setItem('layer_0',
                                    Bag(first_letterhead_record['data']))
        builder = GnrHtmlBuilder(htmlTemplate=base_letterhead_bag)
        builder.initializeSrc()
        height = builder.page_height - builder.page_margin_top - builder.page_margin_bottom
        width = builder.page_width - builder.page_margin_left - builder.page_margin_right
        #page = builder.body.div(height='%imm' %builder.page_height,width='%imm' %builder.page_width,
        #                        position='relative',_class='letterhead_page')

        page = builder.body.div(style="""position:relative;
                                   width:%smm;
                                   height:%smm;
                                   top:0mm;
                                   left:0mm;
                                   """ %
                                (builder.page_width, builder.page_height),
                                _class='letterhead_page')

        builder.letterhead_root = page.div(
            style="""position:absolute;
                                   top:%imm;
                                   left:%imm;
                                   right:%imm;
                                   bottom:%imm;""" %
            (builder.page_margin_top, builder.page_margin_left,
             builder.page_margin_right, builder.page_margin_bottom))

        for i, pkey in enumerate(letterhead_pkeys):
            regions = self.letterhead_layer(builder,
                                            Bag(f[pkey]['data']),
                                            width=width,
                                            height=height,
                                            count=i)
        builder._regions = regions
        regions['center_center'].attributes['content_node'] = 't'
        return builder
Example #8
0
    def __call__(self, record=None, filepath=None, folder=None, filename=None, hideTemplate=False, rebuild=True,
                 htmlContent=None,page_debug=None, is_draft=None, **kwargs):
        """Return the html corresponding to a given record. The html can be loaded from
        a cached document or created as new if still doesn't exist"""
        if record is None:
            record = Bag()
        self.htmlContent = htmlContent
        self._data = Bag()
        self.is_draft = is_draft
        self.record = record
        self.setData('record', record) #compatibility
        for k, v in kwargs.items():
            self.setData(k, v)
        if not filepath:
            folder = folder or tempfile.mkdtemp()
            filepath = os.path.join(folder, filename or self.outputDocName(ext='html'))
        self.filepath = filepath        
        if not rebuild:
            with open(self.filepath, 'r') as f:
                result = f.read()
            return result
            
        self.templates = kwargs.pop('templates', self.templates)
        self.letterhead_id = kwargs.pop('letterhead_id', self.letterhead_id)
        self.print_button = kwargs.pop('print_button', self.print_button)
        if self.onRecordLoaded() is False:
            return False

        self.showTemplate(hideTemplate is not True)
        self.htmlTemplate = None
        self.prepareTemplates()
        self.page_debug = page_debug or self.page_debug
        self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                      page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                      page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                      page_debug=self.page_debug, print_button=self.print_button,
                                      htmlTemplate=self.htmlTemplate, css_requires=self.get_css_requires(),
                                      showTemplateContent=self.showTemplateContent,parent=self)
        result = self.createHtml(filepath=self.filepath,body_attributes=self.body_attributes)
        return result
Example #9
0
class BagToHtml(object):
    """A class that transforms a :ref:`bag` into HTML. It can be used to make a :ref:`print`"""
    css_requires = ''
    templates = ''
    letterhead_id = ''
    currencyFormat = u'#,###.00'
    encoding = 'utf-8'
    page_debug = False
    page_width = 200
    page_height = 280
    page_margin_top = 0
    page_margin_left = 0
    page_margin_right = 0
    page_margin_bottom = 0
    page_header_height = 0
    page_footer_height = 0
    page_leftbar_width = 0
    page_rightbar_width = 0
    print_button = None
    row_mode = 'value'
    rows_path = 'rows'
    doc_header_height = 0 # e.g. 10
    doc_footer_height = 0 # e.g. 15
    grid_header_height = 0 # e.g. 6.2
    grid_footer_height = 0
    grid_col_headers = None
    grid_col_widths = [0, 0, 0]
    grid_row_height = 5
    copies_per_page = 1
    copy_extra_height = 0
    starting_page_number = 0
    body_attributes = None
    
    def __init__(self, locale='en', encoding='utf-8', templates=None, templateLoader=None, **kwargs):
        self.locale = locale
        self.encoding = encoding
        self.thermo_kwargs = None
        self.thermo_wrapper = None
        if templates:
            self.templates = templates
        if templateLoader:
            self.templateLoader = templateLoader
            
    def init(self, *args, **kwargs):
        """A ``init`` hook method"""
        pass
        
    def outputDocName(self, ext=''):
        """Set the filename extension and return it
        
        :param ext: the filename extension"""
        return 'temp.%s' % ext
        
    def onRecordLoaded(self):
        """Hook method. Allow to define the query to be executed for the :ref:`print`
        
        Example::
        
            def onRecordLoaded(self):
                where = '$date >= :begin_date AND $date <= :end_date AND doctor_id=:d_id'
                columns ='''$doctor,$date,$hour,$patient,$performance,
                            @convention_id.code AS convention_code,
                            $amount,$cost,@invoice_id.number AS invoice'''
                query = self.db.table(self.rows_table).query(columns=columns, where=where, 
                                                             begin_data = self.getData('period.from'),
                                                             end_data = self.getData('period.to'),
                                                             d_id=self.record['id'])
                selection = query.selection()
                if not selection:
                    return False
                self.setData('rows',selection.output('grid'))"""
        pass
        
    def orientation(self):
        """Set the page orientation to 'Landscape' if the :ref:`bagtohtml_page_width` is greater
        than the :ref:`bagtohtml_page_height`, else set the orientation to 'Portrait'"""
        if self.page_width>self.page_height:
            return 'Landscape'
        else:
            return 'Portrait'
            
    def __call__(self, record=None, filepath=None, folder=None, filename=None, hideTemplate=False, rebuild=True,
                 htmlContent=None,page_debug=None, is_draft=None, **kwargs):
        """Return the html corresponding to a given record. The html can be loaded from
        a cached document or created as new if still doesn't exist"""
        if record is None:
            record = Bag()
        self.htmlContent = htmlContent
        self._data = Bag()
        self.is_draft = is_draft
        self.record = record
        self.setData('record', record) #compatibility
        for k, v in kwargs.items():
            self.setData(k, v)
        if not filepath:
            folder = folder or tempfile.mkdtemp()
            filepath = os.path.join(folder, filename or self.outputDocName(ext='html'))
        self.filepath = filepath        
        if not rebuild:
            with open(self.filepath, 'r') as f:
                result = f.read()
            return result
            
        self.templates = kwargs.pop('templates', self.templates)
        self.letterhead_id = kwargs.pop('letterhead_id', self.letterhead_id)
        self.print_button = kwargs.pop('print_button', self.print_button)
        if self.onRecordLoaded() is False:
            return False

        self.showTemplate(hideTemplate is not True)
        self.htmlTemplate = None
        self.prepareTemplates()
        self.page_debug = page_debug or self.page_debug
        self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                      page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                      page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                      page_debug=self.page_debug, print_button=self.print_button,
                                      htmlTemplate=self.htmlTemplate, css_requires=self.get_css_requires(),
                                      showTemplateContent=self.showTemplateContent,parent=self)
        result = self.createHtml(filepath=self.filepath,body_attributes=self.body_attributes)
        return result
        
    def get_css_requires(self):
        """Get the :ref:`"css_requires" webpage variable <css_requires>` in its string format
        and return it as a list"""
        return self.css_requires.split(',')
        
    def prepareTemplates(self):
        """Set the correct value of every measure of the page: height, width, header, footer, margins"""
        top_layer = Bag()
        if not self.htmlTemplate:
            self.htmlTemplate = self.templateLoader(letterhead_id=self.letterhead_id,name=self.templates)
            if self.htmlTemplate:
                top_layer =  self.htmlTemplate['#%i' %(len(self.htmlTemplate)-1)]
        d = self.__dict__
        self.page_height = float(d.get('page_height') or top_layer['main.page.height'] or self.page_height)
        self.page_width = float(d.get('page_width') or top_layer['main.page.width'] or self.page_width)
        self.page_margin_top = float(d.get('page_margin_top') or top_layer['main.page.top'] or self.page_margin_top)
        self.page_margin_left = float(d.get('page_margin_left')or top_layer['main.page.left'] or self.page_margin_left)
        self.page_margin_right = float(d.get('page_margin_right')or top_layer['main.page.right'] or self.page_margin_right)
        self.page_margin_bottom = float(d.get('page_margin_bottom') or top_layer['main.page.bottom'] or self.page_margin_bottom)
        self.page_header_height = float(d.get('page_header_height') or top_layer['layout.top?height'] or self.page_header_height)
        self.page_footer_height = float(d.get('page_footer_height') or top_layer['layout.bottom?height'] or self.page_footer_height)
        self.page_leftbar_width = float(d.get('page_leftbar_width') or top_layer['layout.left?width'] or self.page_leftbar_width)
        self.page_rightbar_width = float(d.get('page_rightbar_width')or top_layer['layout.right?width'] or self.page_rightbar_width)

    def toText(self, obj, locale=None, format=None, mask=None, encoding=None, **kwargs):
        """TODO
        
        :param obj: TODO
        :param locale: the current locale (e.g: en, en_us, it)
        :param format: TODO
        :param mask: TODO
        :param encoding: the multibyte character encoding you choose"""
        locale = locale or self.locale
        encoding = locale or self.encoding
        return toText(obj, locale=locale, format=format, mask=mask, encoding=encoding, **kwargs)
        
    def createHtml(self, filepath=None, body_attributes=None):
        """TODO
        
        :param filepath: the path where html will be saved"""
        #filepath = filepath or self.filepath
        self.initializeBuilder(body_attributes=body_attributes)
        self.main()
        self.builder.toHtml(filepath=filepath)
        return self.builder.html
        
    def showTemplate(self, value):
        """TODO
        
        :param value: TODO"""
        self.showTemplateContent = value
        
    def setTemplates(self, templates):
        """Set a template.
        
        :param templates: TODO"""
        self.templates = templates
        
    def getTemplates(self, templates):
        """TODO
        
        :param templates: TODO"""
        return self.templates

    def initializeBuilder(self, body_attributes=None):
        """TODO"""
        self.builder.initializeSrc(body_attributes=body_attributes)
        self.body = self.builder.body
        self.getNewPage = self.builder.newPage
        self.builder.styleForLayout()

    def getNewPage(self):
        pass

        
    def getData(self, path, default=None):
        """Make a :meth:`getItem() <gnr.core.gnrbag.Bag.getItem>` on data if
        ... TODO
        
        :param path: the path of data (e.g: ``'period.from'``)
        :param default: the default return value for a not found item"""
        wildchars = []
        if path[0] in wildchars:
            value = 'not yet implemented'
        else:
            value = self._data.getItem(path, default)
        return value
        
    def setData(self, path, value, **kwargs):
        """Make a :meth:`setItem() <gnr.core.gnrbag.Bag.setItem>` on data
        
        :param path: the path of data (e.g: ``'period.from'``)
        :param default: the default return value for a not found item"""
        self._data.setItem(path, value, **kwargs)
        
    def onRecordExit(self, recordBag):
        """Hook method.
        
        :param recordBag: a :ref:`bag` that contains the result of the batch"""
        return
        
    def field(self, path, default=None, locale=None,
              format=None, mask=None, root=None, **kwargs):
        """TODO
        
        :param path: TODO
        :param default: TODO
        :param locale: the current locale (e.g: en, en_us, it)
        :param format: TODO
        :param mask: TODO
        :param root: the root of the page. For more information, check the
                     :ref:`webpages_main` documentation section"""
        if root is None:
            root = self._data['record']
        attr = {}
        if isinstance(root, Bag):
            datanode = root.getNode(path)
            if datanode:
                value = datanode.value
                attr = datanode.attr
            else:
                value = default
        else:
            value = root.get(path)
        format = format or attr.get('format')
        mask = mask or attr.get('mask')
        if value is None:
            value = default
        elif isinstance(value, Bag) and not format:
            return value
        return self.toText(value, locale, format, mask, self.encoding, **kwargs)
        
    def main(self):
        """It can be overridden"""
        if self.htmlContent:
            page = self.getNewPage()
            page.div("%s::HTML" % self.htmlContent)
        else:
            self.mainLoop()

    def onNewPage(self,page):
        if self.is_draft:
            page.div(style='position:absolute; top:0; left:0; right:0; bottom:0; z-index:10000',_class='document_draft')
            
    def pageCounter(self, mask=None):
        """Allow to automatically number the pages created in a :ref:`print`. You can choose
        the format output with the *mask* parameter
        
        :param mask: format output of the pageCounter method. By default is ``'%s/%s'``
        
                     **Example**: if you print three pages then they will be numbered
                     as `1/3`, `2/3` and `3/3`
                     
                     **Syntax**: You can alternatively set it as ``'%s of %s'``,
                     ``'%s - %s'`` and so on"""
        mask = mask or '%s/%s'
        
        def getPage(currPage=0):
            t = (currPage + 1 + self.starting_page_number,
                             self.current_page_number + 1 + self.starting_page_number)
            if len(mask)-len(mask.replace(r'%s',''))>2:
                result = mask % t
            else:
                result = mask % t[0]
            return result
            
        return BagCbResolver(getPage, currPage=self.current_page_number)

    @property
    def current_page_number(self):
        return self.copies[self.copy]['currPage']

    def copyHeight(self):
        """TODO"""
        return (self.page_height - self.page_margin_top - self.page_margin_bottom -\
                self.page_header_height - self.page_footer_height -\
                self.copy_extra_height * (self.copies_per_page - 1)) / self.copies_per_page
                
    def copyWidth(self):
        """TODO"""
        return (self.page_width - self.page_margin_left - self.page_margin_right -\
                self.page_leftbar_width - self.page_rightbar_width)
                
    def mainLoop(self):
        """TODO"""
        self.copies = []
        self.lastPage = False
        self.defineStandardStyles()
        self.defineCustomStyles()
        self.doc_height = self.copyHeight() #- self.page_header_height - self.page_footer_height
        self.grid_height = self.doc_height - self.calcDocHeaderHeight() - self.calcDocFooterHeight()
        self.grid_body_height = float(self.grid_height or 0) - float(self.grid_header_height or 0) - float(self.grid_footer_height or 0)
        for copy in range(self.copies_per_page):
            self.copies.append(dict(grid_body_used=self.grid_height, currPage=-1))
            
        lines = self.getData(self.rows_path)
        if not lines and hasattr(self,'empty_row'):
            lines = Bag()
            lines.setItem('empty',Bag(self.empty_row),**self.empty_row)
        if lines:
            if isinstance(lines, Bag):
                nodes = lines.getNodes()
            elif hasattr(lines, 'next'):
                nodes = list(lines)
            else:
                nodes = lines
            lastNode = nodes[-1] 
            if hasattr(self, 'thermo_wrapper') and self.thermo_kwargs:
                nodes = self.thermo_wrapper(nodes, **self.thermo_kwargs)
            for rowDataNode in nodes:
                self.isLastRow = rowDataNode is lastNode
                self.currRowDataNode = rowDataNode
                for copy in range(self.copies_per_page):
                    self.onNewRow()
                    self.copy = copy
                    rowheight = self.calcRowHeight()
                    availableSpace = self.grid_height - self.copyValue('grid_body_used') -\
                                     self.calcGridHeaderHeight() - self.calcGridFooterHeight()
                    if rowheight > availableSpace:
                        self._newPage()
                    if not self.rowData:
                        continue
                    row = self.copyValue('body_grid').row(height=rowheight)
                    self.copies[self.copy]['grid_body_used'] = self.copyValue('grid_body_used') + rowheight
                    self.currColumn = 0
                    self.currRow = row
                    self.prepareRow(row)
                    
            for copy in range(self.copies_per_page):
                self.copy = copy
                self._closePage(True)

        
    def onNewRow(self):
        pass
                
    def _newPage(self):
        if self.copyValue('currPage') >= 0:
            self._closePage()
        self.copies[self.copy]['currPage'] = self.copyValue('currPage') + 1
        self.copies[self.copy]['grid_body_used'] = 0
        self._createPage()
        self._openPage()
        
    def _get_rowData(self):
        if isinstance(self.currRowDataNode, dict) or isinstance(self.currRowDataNode,Bag):
            return self.currRowDataNode
        elif self.row_mode == 'attribute':
            return self.currRowDataNode.attr
        else:
            return self.currRowDataNode.value
            
    rowData = property(_get_rowData)
    
    def rowField(self, path=None, **kwargs):
        """TODO
        
        :param path: TODO"""
        #if self.row_mode=='attribute':
        #    data = self.currRowDataNode.attr
        #else:
        #    data = self.currRowDataNode.value
        return self.field(path, root=self.rowData, **kwargs)
        
    def rowCell(self, field=None, value=None, default=None, locale=None,
                format=None, mask=None, currency=None,white_space='nowrap', **kwargs):
                
        """Allow to get data from record. You can use it in the :meth:`prepareRow` method
        
        :param field: the name of the table :ref:`column`
        :param value: TODO
        :param default: TODO
        :param locale: the current locale (e.g: en, en_us, it)
        :param format: the format of the cell (e.g: use ``HH:mm``)
        :param mask: TODO
        :param currency: TODO"""
        
        if field:
            if callable(field):
                value = field()
            else:
                value = self.rowField(field, default=default, locale=locale, format=format,
                                      mask=mask, currency=currency)
        if value is not None:
            #if self.lastPage:
            #    print 'last page'
            #    print self.currColumn
            #    print self.grid_col_widths[self.currColumn]
            value = self.toText(value, locale, format, mask, self.encoding)
            self.currRow.cell(value, width=self.grid_col_widths[self.currColumn], overflow='hidden',
                              white_space=white_space, **kwargs)
        self.currColumn = self.currColumn + 1
        return value

    def _createPage(self):
        curr_copy = self.copies[self.copy]
        if self.copy == 0:
            self.paperPage = self.getNewPage()
            #self.page_header_height = self.page_header_height or getattr(self.builder,'page_header_height')
            #self.page_footer_height = self.page_footer_height or getattr(self.builder,'page_footer_height')

        self.page_layout = self.mainLayout(self.paperPage)
        #if self.page_header_height:
        #    curr_copy['page_header'] = self.page_layout.row(height=self.page_header_height,lbl_height=4,lbl_class='caption').cell()
        if self.calcDocHeaderHeight():
            curr_copy['doc_header'] = self.page_layout.row(height=self.calcDocHeaderHeight(), lbl_height=4,
                                                           lbl_class='caption').cell()
        curr_copy['doc_body'] = self.page_layout.row(height=0, lbl_height=4, lbl_class='caption').cell()
        if self.calcDocFooterHeight():
            curr_copy['doc_footer'] = self.page_layout.row(height=self.doc_footer_height, lbl_height=4,
                                                           lbl_class='caption').cell()
            #if self.page_footer_height:
            #    curr_copy['page_footer'] = self.page_layout.row(height=self.page_footer_height,lbl_height=4,lbl_class='caption').cell()
            
    def mainLayout(self, page):
        """Hook method that must be overridden. It gives the :ref:`print_layout_page`
        object to which you have to append a :meth:`layout <gnr.core.gnrhtml.GnrHtmlSrc.layout>`
        
        :param page: the page object"""
        print 'mainLayout must be overridden'
        
    def _openPage(self):
        #if self.page_header_height:
        #    self.pageHeader(self.copyValue('page_header')) #makeTop
        if self.doc_header_height:
            self.docHeader(self.copyValue('doc_header'))
        self._docBody(self.copyValue('doc_body'))
        
    def _closePage(self, lastPage=None):
        if lastPage:
            self.lastPage = True
        self.fillBodyGrid()
        footer_height = self.calcGridFooterHeight()
        if footer_height:
            row = self.copyValue('body_grid').row(height=footer_height)
            self.currColumn = 0
            self.currRow = row
            self.gridFooter(row)
        if self.calcDocFooterHeight():
            self.docFooter(self.copyValue('doc_footer'), lastPage=lastPage)
            #if self.page_footer_height:
            #    self.pageFooter(self.copyValue('page_footer'),lastPage=lastPage)
            
    def _docBody(self, body):
        header_height = self.calcGridHeaderHeight()
        grid = self.gridLayout(body)
        if header_height:
            self.gridHeader(grid.row(height=header_height))
        self.copies[self.copy]['body_grid'] = grid
        
    def gridLayout(self, grid):
        """Hook method. MANDATORY if you define a :ref:`print_layout_grid` in
        your :ref:`print`. Through this method you receive the center of the page and you can
        define the layout of the grid
        
        :param grid: the :ref:`print_layout_grid`"""
        print 'gridLayout must be overridden'
        
    def gridHeader(self, row):
        """It can be overridden
        
        :param row: the grid row"""
        lbl_height = 4
        headers = self.grid_col_headers
        if ':' in headers:
            headers, lbl_height = headers.split(':')
            lbl_height = int(lbl_height)
        for k, lbl in enumerate(self.grid_col_headers.split(',')):
            style = None
            if lbl == '|':
                lbl = ''
                style = 'border-top:0mm;border-bottom:0mm;'
            row.cell(lbl=lbl, lbl_height=lbl_height, width=self.grid_col_widths[k], style=style)
            
    def gridFooter(self, row):
        """It can be overridden
        
        :param row: the grid row"""
        return
        
    def fillBodyGrid(self):
        """TODO"""
        row = self.copyValue('body_grid').row()
        for w in self.grid_col_widths:
            row.cell(width=w)
            
    def copyValue(self, valuename):
        """TODO
        
        :param valuename: the name of the value to copy"""
        return self.copies[self.copy][valuename]
        
    def calcRowHeight(self):
        """override for special needs"""
        return self.grid_row_height
        
    def calcGridHeaderHeight(self):
        """override for special needs"""
        return self.grid_header_height
        
    def calcGridFooterHeight(self):
        """override for special needs"""
        return self.grid_footer_height
        
    def calcDocHeaderHeight(self):
        """override for special needs"""
        return self.doc_header_height

    def calcDocFooterHeight(self):
        """override for special needs"""
        return self.doc_footer_height
        
    def defineCustomStyles(self):
        """override this for custom styles"""
        pass
        
    def docFooter(self, footer, lastPage=None):
        """Hook method. Define the footer of the :ref:`print_layout_doc` in the :ref:`print_layout`
        
        :param footer: the footer object
        :param lastPage: boolean. More information in the :ref:`lastpage` section
        
        .. note:: the method is called only if the :ref:`bagtohtml_doc_footer_height`
                  has a value different from ``0``"""
        pass
        
    def pageFooter(self, footer, lastPage=None):
        """Hook method. Define the footer of the :ref:`print_layout_page` in the :ref:`print_layout`
        
        :param footer: the footer object
        :param lastPage: boolean. More information in the :ref:`lastpage` section
        
        .. note:: the method is called only if the :ref:`bagtohtml_page_footer_height`
                  has a value different from ``0``"""
        pass
        
    def pageHeader(self, header):
        """Hook method. Define the header of the :ref:`print_layout_page` in the :ref:`print_layout`
        
        :param header: the header object
        
        .. note:: the method is called only if the :ref:`bagtohtml_page_header_height`
                  has a value different from ``0``"""
        pass
        
    def docHeader(self, header):
        """Hook method. Define the header of the :ref:`print_layout_doc` in the :ref:`print_layout`
        
        :param header: the header object
        
        The docHeader() method allows to receive an object called header to which you
        can append a layout structure made by :meth:`layouts <gnr.core.gnrhtml.GnrHtmlSrc.layout>`,
        :meth:`rows <gnr.core.gnrhtml.GnrHtmlSrc.row>`, and :meth:`cells <gnr.core.gnrhtml.GnrHtmlSrc.cell>`
        
        .. note:: the method is called only if the :ref:`bagtohtml_doc_header_height`
                  has a value different from ``0``"""
        pass
        
    def defineStandardStyles(self):
        """TODO"""
        self.body.style("""
      
                        .caption{text-align:center;
                                 color:gray;
                                 font-size:8pt;
                                 height:4mm;
                                 line-height:4mm;
                                 font-weight: normal;
                                 }
                        .smallCaption{font-size:7pt;
                                  text-align:left;
                                  color:gray;
                                  text-indent:1mm;
                                  width:auto;
                                  font-weight: normal;
                                  line-height:auto;
                                  line-height:3mm;
                                  height:3mm;""")

                                  
        self.body.style("""
                        .extrasmall {font-size:6pt;text-align:left;line-height:3mm;}
                        .textfield {text-indent:0mm;margin:1mm;line-height:3mm}
                        .dotted_bottom {border-bottom:1px dotted gray;}
                                                
                        .aligned_right{
                            text-align:right;
                            margin-right:1.5mm;
                        }
                        .aligned_left{
                            text-align:left;
                            margin-left:1.5mm;
                        }
                        .aligned_center{
                            text-align:center;
                        }
                         """)
Example #10
0
 def onIniting(self, request_args=None, request_kwargs=None):
     self.builder = GnrHtmlBuilder(srcfactory=self.srcfactory)
Example #11
0
class RecordToHtmlPage(TableScriptOnRecord):
    maintable = ''
    templates = ''
    rows_path = 'rows'
    html_folder = '*connections/html'
    pdf_folder = '*connections/pdf'
    encoding = 'utf-8'
    page_debug = False
    page_width = 200
    page_height = 280
    page_margin_top = 0
    page_margin_left = 0
    page_margin_right = 0
    page_margin_bottom = 0
    print_button = None
    currencyFormat = u'#,###.00'
    row_mode = 'bag'
    #override these lines
    row_mode = 'value'
    page_header_height = 0 #
    page_footer_height = 0
    page_leftbar_width = 0
    page_rightbar_width = 0
    doc_header_height = 0 # eg 10
    doc_footer_height = 0 # eg 15
    grid_header_height = 0 # eg 6.2
    grid_footer_height = 0
    grid_col_widths = [0, 0, 0]
    grid_row_height = 5
    copies_per_page = 1
    copy_extra_height = 0
    starting_page_number = 0

    def init(self, **kwargs):
        self.maintable = self.maintable or self.resource_table
        self.maintable_obj = self.db.table(self.maintable)
        self.stopped = False

    def __call__(self, record=None, filepath=None,
                 rebuild=False, dontSave=False, pdf=False, runKwargs=None,
                 showTemplateContent=None, **kwargs):
        """This method returns the html corresponding to a given record.
           the html can be loaded from a cached document or created if still doesn't exist.
        """
        if not record:
            return False
        self.showTemplateContent = showTemplateContent or True
        loadResult = self.loadRecord(record, **kwargs)
        if loadResult == False:
            return False
        self.htmlTemplate = None
        if self.templates:
            self.htmlTemplate = self.db.table('adm.htmltemplate').getTemplate(self.templates)
            self.page_height = self.page_height or self.htmlTemplate['main.page.height'] or 280
            self.page_width = self.page_width or self.htmlTemplate['main.page.width'] or 200
            self.page_header_height = self.page_header_height or  self.htmlTemplate['layout.top?height'] or 0
            self.page_footer_height = self.page_footer_height or  self.htmlTemplate['layout.bottom?height'] or 0
            self.page_leftbar_width = self.page_leftbar_width or  self.htmlTemplate['layout.left?width'] or 0
            self.page_rightbar_width = self.page_leftbar_width or  self.htmlTemplate['layout.right?width'] or 0
            self.page_margin_top = self.page_margin_top or self.htmlTemplate['main.page.top'] or 0
            self.page_margin_left = self.page_margin_left or self.htmlTemplate['main.page.left'] or 0
            self.page_margin_right = self.page_margin_right or self.htmlTemplate['main.page.right'] or 0
            self.page_margin_bottom = self.page_margin_bottom or self.htmlTemplate['main.page.bottom'] or 0

        self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                      page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                      page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                      page_debug=self.page_debug, print_button=self.print_button,
                                      htmlTemplate=self.htmlTemplate,
                                      showTemplateContent=self.showTemplateContent)
        #if not (dontSave or pdf):
        self.filepath = filepath or os.path.join(self.hmtlFolderPath(), self.outputDocName(ext='html'))
        #else:
        #    self.filepath = None
        if rebuild or not os.path.isfile(self.filepath):
            html = self.createHtml(filepath=self.filepath, **kwargs)

        else:
            with open(self.filepath, 'r') as f:
                html = f.read()
        if pdf:
            temp = tempfile.NamedTemporaryFile(suffix='.pdf')
            self.page.getService('print').htmlToPdf(self.filepath, temp.name)
            with open(temp.name, 'rb') as f:
                html = f.read()
        self.onRecordExit(self.getData('record'))
        return html

    def toText(self, obj, locale=None, format=None, mask=None, encoding=None, **kwargs):
        locale = locale or self.locale
        encoding = locale or self.encoding
        return toText(obj, locale=locale, format=format, mask=mask, encoding=encoding, **kwargs)

    def createHtml(self, filepath=None, **kwargs):
        #filepath = filepath or self.filepath
        self.initializeBuilder()
        self.main()
        if not self.stopped:
            self.builder.toHtml(filepath=filepath)
            return self.builder.html

    def initializeBuilder(self):
        self.builder.initializeSrc()
        self.body = self.builder.body
        self.getNewPage = self.builder.newPage
        self.builder.styleForLayout()
Example #12
0
class RecordToHtml(TableScriptOnRecord):
    maintable = ''
    templates = ''
    html_folder = '*connections/html'
    pdf_folder = '*connections/pdf'
    encoding = 'utf-8'
    page_debug = False
    page_width = 200
    page_height = 280
    print_button = None
    page_margin_top = 0
    page_margin_left = 0
    page_margin_right = 0
    page_margin_bottom = 0
    htmlTemplate = None


    def init(self, **kwargs):
        self.maintable = self.maintable or self.resource_table
        self.maintable_obj = self.db.table(self.maintable)
        if self.templates:
            self.htmlTemplate = self.db.table('adm.htmltemplate').getTemplate(self.templates)
        self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                      page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                      page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                      page_debug=self.page_debug, print_button=self.print_button,
                                      htmlTemplate=self.htmlTemplate)

    def __call__(self, record=None, filepath=None,
                 rebuild=False, dontSave=False, pdf=False, runKwargs=None, **kwargs):
        """This method returns the html corresponding to a given record.
           the html can be loaded from a cached document or created if still doesn't exist.
        """
        if not record:
            return
        self.loadRecord(record, **kwargs)
        if kwargs:
            self._data['kwargs'] = Bag()
            for k, v in kwargs.items():
                self._data['kwargs.%s' % k] = v

        #if not (dontSave or pdf):
        self.filepath = filepath or os.path.join(self.hmtlFolderPath(), self.outputDocName(ext='html'))
        #else:
        #    self.filepath = None
        if rebuild or not os.path.isfile(self.filepath):
            html = self.createHtml(filepath=self.filepath, **kwargs)

        else:
            with open(self.filepath, 'r') as f:
                html = f.read()
        if pdf:
            temp = tempfile.NamedTemporaryFile(suffix='.pdf')
            self.page.getService('print').htmlToPdf(self.filepath, temp.name)
            with open(temp.name, 'rb') as f:
                html = f.read()
        return html

    def createHtml(self, filepath=None, **kwargs):
        #filepath = filepath or self.filepath
        self.initializeBuilder()
        self.main()
        self.builder.toHtml(filepath=filepath)
        return self.builder.html

    def initializeBuilder(self):
        self.builder.initializeSrc()
        self.body = self.builder.body
        self.getNewPage = self.builder.newPage
        self.builder.styleForLayout()

    def hmtlFolderPath(self):
        return self.getFolderPath(*self.html_folder.split('/'))

    def pdfFolderPath(self):
        return self.getFolderPath(*self.pdf_folder.split('/'))

    def field(self, path, default=None, locale=None,
              format=None, mask=None, root=None):
        root = root or self._data['record']
        datanode = root.getNode(path, default)
        value = datanode.value
        attr = datanode.attr
        if value is None:
            value = default
        if isinstance(value, Bag):
            return value
        format = format or attr.get('format')
        mask = mask or attr.get('mask')
        return self.toText(value, locale, format, mask, self.encoding)

    def toText(self, obj, locale=None, format=None, mask=None, encoding=None):
        locale = locale or self.locale
        encoding = locale or self.encoding
        return toText(obj, locale=locale, format=format, mask=mask, encoding=encoding)
        
Example #13
0
                    top=5,
                    left=5,
                    border_width=0.3,
                    border_color='grey',
                    border_style='solid')

    headers_row = l.row(height=10)
    headers_row.cell('Sigla',
                     width=20,
                     style='text-align:center; font-weight:bold;')
    headers_row.cell('Nome', style='text-indent:10mm; font-weight:bold;')

    for pr in province:
        r = l.row(height=10)
        r.cell(pr['sigla'], width=20, style='text-align:center;')
        r.cell(pr['nome'], style='text-indent:10mm;')


if __name__ == '__main__':
    builder = GnrHtmlBuilder(page_height=297,
                             page_width=21,
                             page_margin_top=5,
                             page_margin_left=5)
    builder.initializeSrc()
    builder.styleForLayout()

    example_1(builder.body)

    builder.toHtml('/Users/saverioporcari/esempi_stampa/example.html')
    builder.toPdf('/Users/saverioporcari/esempi_stampa/example.pdf')
Example #14
0
    sandbox_app = GnrApp('sandbox')
    glbl_table = sandbox_app.db.table('glbl.provincia')
    province = glbl_table.query().fetch()

    l = body.layout(width=200,top=5,left=5,
        border_width=0.3,
        border_color='grey',
        border_style='solid')
    
    headers_row = l.row(height=10)
    headers_row.cell('Sigla', width=20, style='text-align:center; font-weight:bold;')
    headers_row.cell('Nome', style='text-indent:10mm; font-weight:bold;')

    for pr in province:
        r = l.row(height=10)
        r.cell(pr['sigla'], width=20, style='text-align:center;')
        r.cell(pr['nome'],  style='text-indent:10mm;')

if __name__ == '__main__':
    builder = GnrHtmlBuilder(page_height=297, page_width=21, page_margin_top=5,
                             page_margin_left=5)
    builder.initializeSrc()
    builder.styleForLayout()

    example_1(builder.body)

    builder.toHtml('/Users/saverioporcari/esempi_stampa/example.html')
    builder.toPdf('/Users/saverioporcari/esempi_stampa/example.pdf')

Example #15
0
class BagToHtml(object):
    """A class that transforms a :ref:`bag` into HTML. It can be used to make a :ref:`print`"""
    css_requires = ''
    templates = ''
    letterhead_id = ''
    currencyFormat = u'#,###.00'
    encoding = 'utf-8'
    page_debug = False
    page_width = 200
    page_height = 280
    page_margin_top = 0
    page_margin_left = 0
    page_margin_right = 0
    page_margin_bottom = 0
    page_header_height = 0
    page_footer_height = 0
    page_leftbar_width = 0
    page_rightbar_width = 0
    print_button = None
    row_mode = 'value'
    rows_path = 'rows'
    doc_header_height = 0  # e.g. 10
    doc_footer_height = 0  # e.g. 15
    grid_header_height = 0  # e.g. 6.2
    grid_footer_height = 0
    grid_col_headers = None
    grid_col_widths = [0, 0, 0]
    grid_row_height = 5
    copies_per_page = 1
    copy_extra_height = 0
    starting_page_number = 0
    body_attributes = None

    def __init__(self,
                 locale='en',
                 encoding='utf-8',
                 templates=None,
                 templateLoader=None,
                 **kwargs):
        self.locale = locale
        self.encoding = encoding
        self.thermo_kwargs = None
        self.thermo_wrapper = None
        if templates:
            self.templates = templates
        if templateLoader:
            self.templateLoader = templateLoader

    def init(self, *args, **kwargs):
        """A ``init`` hook method"""
        pass

    def outputDocName(self, ext=''):
        """Set the filename extension and return it
        
        :param ext: the filename extension"""
        return 'temp.%s' % ext

    def onRecordLoaded(self):
        """Hook method. Allow to define the query to be executed for the :ref:`print`
        
        Example::
        
            def onRecordLoaded(self):
                where = '$date >= :begin_date AND $date <= :end_date AND doctor_id=:d_id'
                columns ='''$doctor,$date,$hour,$patient,$performance,
                            @convention_id.code AS convention_code,
                            $amount,$cost,@invoice_id.number AS invoice'''
                query = self.db.table(self.rows_table).query(columns=columns, where=where, 
                                                             begin_data = self.getData('period.from'),
                                                             end_data = self.getData('period.to'),
                                                             d_id=self.record['id'])
                selection = query.selection()
                if not selection:
                    return False
                self.setData('rows',selection.output('grid'))"""
        pass

    def orientation(self):
        """Set the page orientation to 'Landscape' if the :ref:`bagtohtml_page_width` is greater
        than the :ref:`bagtohtml_page_height`, else set the orientation to 'Portrait'"""
        if self.page_width > self.page_height:
            return 'Landscape'
        else:
            return 'Portrait'

    def __call__(self,
                 record=None,
                 filepath=None,
                 folder=None,
                 filename=None,
                 hideTemplate=False,
                 rebuild=True,
                 htmlContent=None,
                 page_debug=None,
                 is_draft=None,
                 **kwargs):
        """Return the html corresponding to a given record. The html can be loaded from
        a cached document or created as new if still doesn't exist"""
        if record is None:
            record = Bag()
        self.htmlContent = htmlContent
        self._data = Bag()
        self.is_draft = is_draft
        self.record = record
        self.setData('record', record)  #compatibility
        for k, v in kwargs.items():
            self.setData(k, v)
        if not filepath:
            folder = folder or tempfile.mkdtemp()
            filepath = os.path.join(folder, filename
                                    or self.outputDocName(ext='html'))
        self.filepath = filepath
        if not rebuild:
            with open(self.filepath, 'r') as f:
                result = f.read()
            return result

        self.templates = kwargs.pop('templates', self.templates)
        self.letterhead_id = kwargs.pop('letterhead_id', self.letterhead_id)
        self.print_button = kwargs.pop('print_button', self.print_button)
        if self.onRecordLoaded() is False:
            return False

        self.showTemplate(hideTemplate is not True)
        self.htmlTemplate = None
        self.prepareTemplates()
        self.page_debug = page_debug or self.page_debug
        self.builder = GnrHtmlBuilder(
            page_width=self.page_width,
            page_height=self.page_height,
            page_margin_top=self.page_margin_top,
            page_margin_bottom=self.page_margin_bottom,
            page_margin_left=self.page_margin_left,
            page_margin_right=self.page_margin_right,
            page_debug=self.page_debug,
            print_button=self.print_button,
            htmlTemplate=self.htmlTemplate,
            css_requires=self.get_css_requires(),
            showTemplateContent=self.showTemplateContent,
            parent=self)
        result = self.createHtml(filepath=self.filepath,
                                 body_attributes=self.body_attributes)
        return result

    def get_css_requires(self):
        """Get the :ref:`"css_requires" webpage variable <css_requires>` in its string format
        and return it as a list"""
        return self.css_requires.split(',')

    def prepareTemplates(self):
        """Set the correct value of every measure of the page: height, width, header, footer, margins"""
        top_layer = Bag()
        if not self.htmlTemplate:
            self.htmlTemplate = self.templateLoader(
                letterhead_id=self.letterhead_id, name=self.templates)
            if self.htmlTemplate:
                top_layer = self.htmlTemplate['#%i' %
                                              (len(self.htmlTemplate) - 1)]
        d = self.__dict__
        self.page_height = float(
            d.get('page_height') or top_layer['main.page.height']
            or self.page_height)
        self.page_width = float(
            d.get('page_width') or top_layer['main.page.width']
            or self.page_width)
        self.page_margin_top = float(
            d.get('page_margin_top') or top_layer['main.page.top']
            or self.page_margin_top)
        self.page_margin_left = float(
            d.get('page_margin_left') or top_layer['main.page.left']
            or self.page_margin_left)
        self.page_margin_right = float(
            d.get('page_margin_right') or top_layer['main.page.right']
            or self.page_margin_right)
        self.page_margin_bottom = float(
            d.get('page_margin_bottom') or top_layer['main.page.bottom']
            or self.page_margin_bottom)
        self.page_header_height = float(
            d.get('page_header_height') or top_layer['layout.top?height']
            or self.page_header_height)
        self.page_footer_height = float(
            d.get('page_footer_height') or top_layer['layout.bottom?height']
            or self.page_footer_height)
        self.page_leftbar_width = float(
            d.get('page_leftbar_width') or top_layer['layout.left?width']
            or self.page_leftbar_width)
        self.page_rightbar_width = float(
            d.get('page_rightbar_width') or top_layer['layout.right?width']
            or self.page_rightbar_width)

    def toText(self,
               obj,
               locale=None,
               format=None,
               mask=None,
               encoding=None,
               **kwargs):
        """TODO
        
        :param obj: TODO
        :param locale: the current locale (e.g: en, en_us, it)
        :param format: TODO
        :param mask: TODO
        :param encoding: the multibyte character encoding you choose"""
        locale = locale or self.locale
        encoding = locale or self.encoding
        return toText(obj,
                      locale=locale,
                      format=format,
                      mask=mask,
                      encoding=encoding,
                      **kwargs)

    def createHtml(self, filepath=None, body_attributes=None):
        """TODO
        
        :param filepath: the path where html will be saved"""
        #filepath = filepath or self.filepath
        self.initializeBuilder(body_attributes=body_attributes)
        self.main()
        self.builder.toHtml(filepath=filepath)
        return self.builder.html

    def showTemplate(self, value):
        """TODO
        
        :param value: TODO"""
        self.showTemplateContent = value

    def setTemplates(self, templates):
        """Set a template.
        
        :param templates: TODO"""
        self.templates = templates

    def getTemplates(self, templates):
        """TODO
        
        :param templates: TODO"""
        return self.templates

    def initializeBuilder(self, body_attributes=None):
        """TODO"""
        self.builder.initializeSrc(body_attributes=body_attributes)
        self.body = self.builder.body
        self.getNewPage = self.builder.newPage
        self.builder.styleForLayout()

    def getNewPage(self):
        pass

    def getData(self, path, default=None):
        """Make a :meth:`getItem() <gnr.core.gnrbag.Bag.getItem>` on data if
        ... TODO
        
        :param path: the path of data (e.g: ``'period.from'``)
        :param default: the default return value for a not found item"""
        wildchars = []
        if path[0] in wildchars:
            value = 'not yet implemented'
        else:
            value = self._data.getItem(path, default)
        return value

    def setData(self, path, value, **kwargs):
        """Make a :meth:`setItem() <gnr.core.gnrbag.Bag.setItem>` on data
        
        :param path: the path of data (e.g: ``'period.from'``)
        :param default: the default return value for a not found item"""
        self._data.setItem(path, value, **kwargs)

    def onRecordExit(self, recordBag):
        """Hook method.
        
        :param recordBag: a :ref:`bag` that contains the result of the batch"""
        return

    def field(self,
              path,
              default=None,
              locale=None,
              format=None,
              mask=None,
              root=None,
              **kwargs):
        """TODO
        
        :param path: TODO
        :param default: TODO
        :param locale: the current locale (e.g: en, en_us, it)
        :param format: TODO
        :param mask: TODO
        :param root: the root of the page. For more information, check the
                     :ref:`webpages_main` documentation section"""
        if root is None:
            root = self._data['record']
        attr = {}
        if isinstance(root, Bag):
            datanode = root.getNode(path)
            if datanode:
                value = datanode.value
                attr = datanode.attr
            else:
                value = default
        else:
            value = root.get(path)
        format = format or attr.get('format')
        mask = mask or attr.get('mask')
        if value is None:
            value = default
        elif isinstance(value, Bag) and not format:
            return value
        return self.toText(value, locale, format, mask, self.encoding,
                           **kwargs)

    def main(self):
        """It can be overridden"""
        if self.htmlContent:
            page = self.getNewPage()
            page.div("%s::HTML" % self.htmlContent)
        else:
            self.mainLoop()

    def onNewPage(self, page):
        if self.is_draft:
            page.div(
                style=
                'position:absolute; top:0; left:0; right:0; bottom:0; z-index:10000',
                _class='document_draft')

    def pageCounter(self, mask=None):
        """Allow to automatically number the pages created in a :ref:`print`. You can choose
        the format output with the *mask* parameter
        
        :param mask: format output of the pageCounter method. By default is ``'%s/%s'``
        
                     **Example**: if you print three pages then they will be numbered
                     as `1/3`, `2/3` and `3/3`
                     
                     **Syntax**: You can alternatively set it as ``'%s of %s'``,
                     ``'%s - %s'`` and so on"""
        mask = mask or '%s/%s'

        def getPage(currPage=0):
            result = mask % (currPage + 1 + self.starting_page_number,
                             self.copies[self.copy]['currPage'] + 1 +
                             self.starting_page_number)
            return result

        return BagCbResolver(getPage,
                             currPage=self.copies[self.copy]['currPage'])

    def copyHeight(self):
        """TODO"""
        return (self.page_height - self.page_margin_top - self.page_margin_bottom -\
                self.page_header_height - self.page_footer_height -\
                self.copy_extra_height * (self.copies_per_page - 1)) / self.copies_per_page

    def copyWidth(self):
        """TODO"""
        return (self.page_width - self.page_margin_left - self.page_margin_right -\
                self.page_leftbar_width - self.page_rightbar_width)

    def mainLoop(self):
        """TODO"""
        self.copies = []
        self.lastPage = False
        self.defineStandardStyles()
        self.defineCustomStyles()
        self.doc_height = self.copyHeight(
        )  #- self.page_header_height - self.page_footer_height
        self.grid_height = self.doc_height - self.calcDocHeaderHeight(
        ) - self.calcDocFooterHeight()
        self.grid_body_height = float(self.grid_height or 0) - float(
            self.grid_header_height or 0) - float(self.grid_footer_height or 0)
        for copy in range(self.copies_per_page):
            self.copies.append(
                dict(grid_body_used=self.grid_height, currPage=-1))

        lines = self.getData(self.rows_path)
        if not lines and hasattr(self, 'empty_row'):
            lines = Bag()
            lines.setItem('empty', Bag(self.empty_row), **self.empty_row)
        if lines:
            if isinstance(lines, Bag):
                nodes = lines.getNodes()
            elif hasattr(lines, 'next'):
                nodes = list(lines)
            else:
                nodes = lines
            lastNode = nodes[-1]
            if hasattr(self, 'thermo_wrapper') and self.thermo_kwargs:
                nodes = self.thermo_wrapper(nodes, **self.thermo_kwargs)
            for rowDataNode in nodes:
                self.isLastRow = rowDataNode is lastNode
                self.currRowDataNode = rowDataNode
                for copy in range(self.copies_per_page):
                    self.onNewRow()
                    self.copy = copy
                    rowheight = self.calcRowHeight()
                    availableSpace = self.grid_height - self.copyValue('grid_body_used') -\
                                     self.calcGridHeaderHeight() - self.calcGridFooterHeight()
                    if rowheight > availableSpace:
                        self._newPage()
                    if not self.rowData:
                        continue
                    row = self.copyValue('body_grid').row(height=rowheight)
                    self.copies[self.copy]['grid_body_used'] = self.copyValue(
                        'grid_body_used') + rowheight
                    self.currColumn = 0
                    self.currRow = row
                    self.prepareRow(row)

            for copy in range(self.copies_per_page):
                self.copy = copy
                self._closePage(True)

    def onNewRow(self):
        pass

    def _newPage(self):
        if self.copyValue('currPage') >= 0:
            self._closePage()
        self.copies[self.copy]['currPage'] = self.copyValue('currPage') + 1
        self.copies[self.copy]['grid_body_used'] = 0
        self._createPage()
        self._openPage()

    def _get_rowData(self):
        if isinstance(self.currRowDataNode, dict) or isinstance(
                self.currRowDataNode, Bag):
            return self.currRowDataNode
        elif self.row_mode == 'attribute':
            return self.currRowDataNode.attr
        else:
            return self.currRowDataNode.value

    rowData = property(_get_rowData)

    def rowField(self, path=None, **kwargs):
        """TODO
        
        :param path: TODO"""
        #if self.row_mode=='attribute':
        #    data = self.currRowDataNode.attr
        #else:
        #    data = self.currRowDataNode.value
        return self.field(path, root=self.rowData, **kwargs)

    def rowCell(self,
                field=None,
                value=None,
                default=None,
                locale=None,
                format=None,
                mask=None,
                currency=None,
                white_space='nowrap',
                **kwargs):
        """Allow to get data from record. You can use it in the :meth:`prepareRow` method
        
        :param field: the name of the table :ref:`column`
        :param value: TODO
        :param default: TODO
        :param locale: the current locale (e.g: en, en_us, it)
        :param format: the format of the cell (e.g: use ``HH:mm``)
        :param mask: TODO
        :param currency: TODO"""

        if field:
            if callable(field):
                value = field()
            else:
                value = self.rowField(field,
                                      default=default,
                                      locale=locale,
                                      format=format,
                                      mask=mask,
                                      currency=currency)
        if value is not None:
            #if self.lastPage:
            #    print 'last page'
            #    print self.currColumn
            #    print self.grid_col_widths[self.currColumn]
            value = self.toText(value, locale, format, mask, self.encoding)
            self.currRow.cell(value,
                              width=self.grid_col_widths[self.currColumn],
                              overflow='hidden',
                              white_space=white_space,
                              **kwargs)
        self.currColumn = self.currColumn + 1
        return value

    def _createPage(self):
        curr_copy = self.copies[self.copy]
        if self.copy == 0:
            self.paperPage = self.getNewPage()
            #self.page_header_height = self.page_header_height or getattr(self.builder,'page_header_height')
            #self.page_footer_height = self.page_footer_height or getattr(self.builder,'page_footer_height')

        self.page_layout = self.mainLayout(self.paperPage)
        #if self.page_header_height:
        #    curr_copy['page_header'] = self.page_layout.row(height=self.page_header_height,lbl_height=4,lbl_class='caption').cell()
        if self.calcDocHeaderHeight():
            curr_copy['doc_header'] = self.page_layout.row(
                height=self.calcDocHeaderHeight(),
                lbl_height=4,
                lbl_class='caption').cell()
        curr_copy['doc_body'] = self.page_layout.row(
            height=0, lbl_height=4, lbl_class='caption').cell()
        if self.calcDocFooterHeight():
            curr_copy['doc_footer'] = self.page_layout.row(
                height=self.doc_footer_height,
                lbl_height=4,
                lbl_class='caption').cell()
            #if self.page_footer_height:
            #    curr_copy['page_footer'] = self.page_layout.row(height=self.page_footer_height,lbl_height=4,lbl_class='caption').cell()

    def mainLayout(self, page):
        """Hook method that must be overridden. It gives the :ref:`print_layout_page`
        object to which you have to append a :meth:`layout <gnr.core.gnrhtml.GnrHtmlSrc.layout>`
        
        :param page: the page object"""
        print 'mainLayout must be overridden'

    def _openPage(self):
        #if self.page_header_height:
        #    self.pageHeader(self.copyValue('page_header')) #makeTop
        if self.doc_header_height:
            self.docHeader(self.copyValue('doc_header'))
        self._docBody(self.copyValue('doc_body'))

    def _closePage(self, lastPage=None):
        if lastPage:
            self.lastPage = True
        self.fillBodyGrid()
        footer_height = self.calcGridFooterHeight()
        if footer_height:
            row = self.copyValue('body_grid').row(height=footer_height)
            self.currColumn = 0
            self.currRow = row
            self.gridFooter(row)
        if self.calcDocFooterHeight():
            self.docFooter(self.copyValue('doc_footer'), lastPage=lastPage)
            #if self.page_footer_height:
            #    self.pageFooter(self.copyValue('page_footer'),lastPage=lastPage)

    def _docBody(self, body):
        header_height = self.calcGridHeaderHeight()
        grid = self.gridLayout(body)
        if header_height:
            self.gridHeader(grid.row(height=header_height))
        self.copies[self.copy]['body_grid'] = grid

    def gridLayout(self, grid):
        """Hook method. MANDATORY if you define a :ref:`print_layout_grid` in
        your :ref:`print`. Through this method you receive the center of the page and you can
        define the layout of the grid
        
        :param grid: the :ref:`print_layout_grid`"""
        print 'gridLayout must be overridden'

    def gridHeader(self, row):
        """It can be overridden
        
        :param row: the grid row"""
        lbl_height = 4
        headers = self.grid_col_headers
        if ':' in headers:
            headers, lbl_height = headers.split(':')
            lbl_height = int(lbl_height)
        for k, lbl in enumerate(self.grid_col_headers.split(',')):
            style = None
            if lbl == '|':
                lbl = ''
                style = 'border-top:0mm;border-bottom:0mm;'
            row.cell(lbl=lbl,
                     lbl_height=lbl_height,
                     width=self.grid_col_widths[k],
                     style=style)

    def gridFooter(self, row):
        """It can be overridden
        
        :param row: the grid row"""
        return

    def fillBodyGrid(self):
        """TODO"""
        row = self.copyValue('body_grid').row()
        for w in self.grid_col_widths:
            row.cell(width=w)

    def copyValue(self, valuename):
        """TODO
        
        :param valuename: the name of the value to copy"""
        return self.copies[self.copy][valuename]

    def calcRowHeight(self):
        """override for special needs"""
        return self.grid_row_height

    def calcGridHeaderHeight(self):
        """override for special needs"""
        return self.grid_header_height

    def calcGridFooterHeight(self):
        """override for special needs"""
        return self.grid_footer_height

    def calcDocHeaderHeight(self):
        """override for special needs"""
        return self.doc_header_height

    def calcDocFooterHeight(self):
        """override for special needs"""
        return self.doc_footer_height

    def defineCustomStyles(self):
        """override this for custom styles"""
        pass

    def docFooter(self, footer, lastPage=None):
        """Hook method. Define the footer of the :ref:`print_layout_doc` in the :ref:`print_layout`
        
        :param footer: the footer object
        :param lastPage: boolean. More information in the :ref:`lastpage` section
        
        .. note:: the method is called only if the :ref:`bagtohtml_doc_footer_height`
                  has a value different from ``0``"""
        pass

    def pageFooter(self, footer, lastPage=None):
        """Hook method. Define the footer of the :ref:`print_layout_page` in the :ref:`print_layout`
        
        :param footer: the footer object
        :param lastPage: boolean. More information in the :ref:`lastpage` section
        
        .. note:: the method is called only if the :ref:`bagtohtml_page_footer_height`
                  has a value different from ``0``"""
        pass

    def pageHeader(self, header):
        """Hook method. Define the header of the :ref:`print_layout_page` in the :ref:`print_layout`
        
        :param header: the header object
        
        .. note:: the method is called only if the :ref:`bagtohtml_page_header_height`
                  has a value different from ``0``"""
        pass

    def docHeader(self, header):
        """Hook method. Define the header of the :ref:`print_layout_doc` in the :ref:`print_layout`
        
        :param header: the header object
        
        The docHeader() method allows to receive an object called header to which you
        can append a layout structure made by :meth:`layouts <gnr.core.gnrhtml.GnrHtmlSrc.layout>`,
        :meth:`rows <gnr.core.gnrhtml.GnrHtmlSrc.row>`, and :meth:`cells <gnr.core.gnrhtml.GnrHtmlSrc.cell>`
        
        .. note:: the method is called only if the :ref:`bagtohtml_doc_header_height`
                  has a value different from ``0``"""
        pass

    def defineStandardStyles(self):
        """TODO"""
        self.body.style("""
      
                        .caption{text-align:center;
                                 color:gray;
                                 font-size:8pt;
                                 height:4mm;
                                 line-height:4mm;
                                 font-weight: normal;
                                 }
                        .smallCaption{font-size:7pt;
                                  text-align:left;
                                  color:gray;
                                  text-indent:1mm;
                                  width:auto;
                                  font-weight: normal;
                                  line-height:auto;
                                  line-height:3mm;
                                  height:3mm;""")

        self.body.style("""
                        .extrasmall {font-size:6pt;text-align:left;line-height:3mm;}
                        .textfield {text-indent:0mm;margin:1mm;line-height:3mm}
                        .dotted_bottom {border-bottom:1px dotted gray;}
                                                
                        .aligned_right{
                            text-align:right;
                            margin-right:1.5mm;
                        }
                        .aligned_left{
                            text-align:left;
                            margin-left:1.5mm;
                        }
                        .aligned_center{
                            text-align:center;
                        }
                         """)
Example #16
0
class RecordToHtmlPage(TableScriptOnRecord):
    maintable = ''
    templates = ''
    rows_path = 'rows'
    html_folder = '*connections/html'
    pdf_folder = '*connections/pdf'
    encoding = 'utf-8'
    page_debug = False
    page_width = 200
    page_height = 280
    page_margin_top = 0
    page_margin_left = 0
    page_margin_right = 0
    page_margin_bottom = 0
    print_button = None
    currencyFormat = u'#,###.00'
    row_mode = 'bag'
    #override these lines
    row_mode = 'value'
    page_header_height = 0  #
    page_footer_height = 0
    page_leftbar_width = 0
    page_rightbar_width = 0
    doc_header_height = 0  # eg 10
    doc_footer_height = 0  # eg 15
    grid_header_height = 0  # eg 6.2
    grid_footer_height = 0
    grid_col_widths = [0, 0, 0]
    grid_row_height = 5
    copies_per_page = 1
    copy_extra_height = 0
    starting_page_number = 0

    def init(self, **kwargs):
        self.maintable = self.maintable or self.resource_table
        self.maintable_obj = self.db.table(self.maintable)
        self.rows_table_obj = None
        if self.rows_table:
            self.rows_table_obj = self.db.table(self.rows_table)
        self.stopped = False

    def __call__(self,
                 record=None,
                 filepath=None,
                 rebuild=False,
                 dontSave=False,
                 pdf=False,
                 runKwargs=None,
                 showTemplateContent=None,
                 **kwargs):
        """This method returns the html corresponding to a given record.
           the html can be loaded from a cached document or created if still doesn't exist.
        """
        if not record:
            return False
        self.showTemplateContent = showTemplateContent or True
        loadResult = self.loadRecord(record, **kwargs)
        if loadResult == False:
            return False
        self.htmlTemplate = None
        if self.templates:
            self.htmlTemplate = self.db.table('adm.htmltemplate').getTemplate(
                self.templates)
            self.page_height = self.page_height or self.htmlTemplate[
                'main.page.height'] or 280
            self.page_width = self.page_width or self.htmlTemplate[
                'main.page.width'] or 200
            self.page_header_height = self.page_header_height or self.htmlTemplate[
                'layout.top?height'] or 0
            self.page_footer_height = self.page_footer_height or self.htmlTemplate[
                'layout.bottom?height'] or 0
            self.page_leftbar_width = self.page_leftbar_width or self.htmlTemplate[
                'layout.left?width'] or 0
            self.page_rightbar_width = self.page_leftbar_width or self.htmlTemplate[
                'layout.right?width'] or 0
            self.page_margin_top = self.page_margin_top or self.htmlTemplate[
                'main.page.top'] or 0
            self.page_margin_left = self.page_margin_left or self.htmlTemplate[
                'main.page.left'] or 0
            self.page_margin_right = self.page_margin_right or self.htmlTemplate[
                'main.page.right'] or 0
            self.page_margin_bottom = self.page_margin_bottom or self.htmlTemplate[
                'main.page.bottom'] or 0

        self.builder = GnrHtmlBuilder(
            page_width=self.page_width,
            page_height=self.page_height,
            page_margin_top=self.page_margin_top,
            page_margin_bottom=self.page_margin_bottom,
            page_margin_left=self.page_margin_left,
            page_margin_right=self.page_margin_right,
            page_debug=self.page_debug,
            print_button=self.print_button,
            htmlTemplate=self.htmlTemplate,
            showTemplateContent=self.showTemplateContent)
        #if not (dontSave or pdf):
        self.filepath = filepath or os.path.join(
            self.hmtlFolderPath(), self.outputDocName(ext='html'))
        #else:
        #    self.filepath = None
        if rebuild or not os.path.isfile(self.filepath):
            html = self.createHtml(filepath=self.filepath, **kwargs)

        else:
            with open(self.filepath, 'r') as f:
                html = f.read()
        if pdf:
            temp = tempfile.NamedTemporaryFile(suffix='.pdf')
            self.page.getService('print').htmlToPdf(self.filepath, temp.name)
            with open(temp.name, 'rb') as f:
                html = f.read()
        self.onRecordExit(self.getData('record'))
        return html

    def toText(self,
               obj,
               locale=None,
               format=None,
               mask=None,
               encoding=None,
               **kwargs):
        locale = locale or self.locale
        encoding = locale or self.encoding
        return toText(obj,
                      locale=locale,
                      format=format,
                      mask=mask,
                      encoding=encoding,
                      **kwargs)

    def createHtml(self, filepath=None, **kwargs):
        #filepath = filepath or self.filepath
        self.initializeBuilder()
        self.main()
        if not self.stopped:
            self.builder.toHtml(filepath=filepath)
            return self.builder.html

    def initializeBuilder(self):
        self.builder.initializeSrc()
        self.body = self.builder.body
        self.getNewPage = self.builder.newPage
        self.builder.styleForLayout()
Example #17
0
class RecordToHtml(TableScriptOnRecord):
    maintable = ''
    templates = ''
    html_folder = '*connections/html'
    pdf_folder = '*connections/pdf'
    encoding = 'utf-8'
    page_debug = False
    page_width = 200
    page_height = 280
    print_button = None
    page_margin_top = 0
    page_margin_left = 0
    page_margin_right = 0
    page_margin_bottom = 0
    htmlTemplate = None

    def init(self, **kwargs):
        self.maintable = self.maintable or self.resource_table
        self.maintable_obj = self.db.table(self.maintable)
        if self.templates:
            self.htmlTemplate = self.db.table('adm.htmltemplate').getTemplate(
                self.templates)
        self.builder = GnrHtmlBuilder(
            page_width=self.page_width,
            page_height=self.page_height,
            page_margin_top=self.page_margin_top,
            page_margin_bottom=self.page_margin_bottom,
            page_margin_left=self.page_margin_left,
            page_margin_right=self.page_margin_right,
            page_debug=self.page_debug,
            print_button=self.print_button,
            htmlTemplate=self.htmlTemplate)

    def __call__(self,
                 record=None,
                 filepath=None,
                 rebuild=False,
                 dontSave=False,
                 pdf=False,
                 runKwargs=None,
                 **kwargs):
        """This method returns the html corresponding to a given record.
           the html can be loaded from a cached document or created if still doesn't exist.
        """
        if not record:
            return
        self.loadRecord(record, **kwargs)
        if kwargs:
            self._data['kwargs'] = Bag()
            for k, v in kwargs.items():
                self._data['kwargs.%s' % k] = v

        #if not (dontSave or pdf):
        self.filepath = filepath or os.path.join(
            self.hmtlFolderPath(), self.outputDocName(ext='html'))
        #else:
        #    self.filepath = None
        if rebuild or not os.path.isfile(self.filepath):
            html = self.createHtml(filepath=self.filepath, **kwargs)

        else:
            with open(self.filepath, 'r') as f:
                html = f.read()
        if pdf:
            temp = tempfile.NamedTemporaryFile(suffix='.pdf')
            self.page.getService('print').htmlToPdf(self.filepath, temp.name)
            with open(temp.name, 'rb') as f:
                html = f.read()
        return html

    def createHtml(self, filepath=None, **kwargs):
        #filepath = filepath or self.filepath
        self.initializeBuilder()
        self.main()
        self.builder.toHtml(filepath=filepath)
        return self.builder.html

    def initializeBuilder(self):
        self.builder.initializeSrc()
        self.body = self.builder.body
        self.getNewPage = self.builder.newPage
        self.builder.styleForLayout()

    def hmtlFolderPath(self):
        return self.getFolderPath(*self.html_folder.split('/'))

    def pdfFolderPath(self):
        return self.getFolderPath(*self.pdf_folder.split('/'))

    def field(self,
              path,
              default=None,
              locale=None,
              format=None,
              mask=None,
              root=None):
        root = root or self._data['record']
        datanode = root.getNode(path, default)
        value = datanode.value
        attr = datanode.attr
        if value is None:
            value = default
        if isinstance(value, Bag):
            return value
        format = format or attr.get('format')
        mask = mask or attr.get('mask')
        return self.toText(value, locale, format, mask, self.encoding)

    def toText(self, obj, locale=None, format=None, mask=None, encoding=None):
        locale = locale or self.locale
        encoding = locale or self.encoding
        return toText(obj,
                      locale=locale,
                      format=format,
                      mask=mask,
                      encoding=encoding)
Example #18
0
class BagToHtml(object):
    """add???
    """
    templates = ''
    print_button = None
    rows_path = 'rows'
    encoding = 'utf-8'
    page_debug = False
    page_width = 200
    page_height = 280
    page_margin_top = 0
    page_margin_left = 0
    page_margin_right = 0
    page_margin_bottom = 0
    currencyFormat = u'#,###.00'
    #override these lines
    row_mode = 'value'
    page_header_height = 0 #
    page_footer_height = 0
    page_leftbar_width = 0
    page_rightbar_width = 0
    doc_header_height = 0 # eg 10
    doc_footer_height = 0 # eg 15
    grid_header_height = 0 # eg 6.2
    grid_footer_height = 0
    grid_col_widths = [0, 0, 0]
    grid_row_height = 5
    copies_per_page = 1
    copy_extra_height = 0
    starting_page_number = 0
    css_requires = ''
    
    def __init__(self, locale='en', encoding='utf-8', templates=None, templateLoader=None, **kwargs):
        self.locale = locale
        self.encoding = encoding
        self.thermo_kwargs = None
        self.thermo_wrapper = None
        if templates:
            self.templates = templates
        if templateLoader:
            self.templateLoader = templateLoader
            
    def init(self, *args, **kwargs):
        """add???"""
        pass
        
    def outputDocName(self, ext=''):
        """add???
        
        :param ext: add???. Default value is `` ``
        """
        return 'temp.%s' % ext
        
    def onRecordLoaded(self):
        """override this"""
        pass
        
    def orientation(self):
        """add???
        """
        if self.page_width>self.page_height:
            return 'Landscape'
        else:
            return 'Portrait'
        
    def __call__(self, record=None, filepath=None, folder=None, filename=None, hideTemplate=False, rebuild=True,
                 htmlContent=None, **kwargs):
        """Return the html corresponding to a given record.
        The html can be loaded from a cached document or created if still doesn't exist.
        """
        if record is None:
            record = Bag()
        self.htmlContent = htmlContent
        self._data = Bag()
        self.record = record
        self.setData('record', record) #compatibility
        for k, v in kwargs.items():
            self.setData(k, v)
        if folder and not filepath:
            filepath = os.path.join(folder, filename or self.outputDocName(ext='html'))
        self.filepath = filepath
        
        if not rebuild:
            with open(self.filepath, 'r') as f:
                result = f.read()
            return result
            
        self.templates = kwargs.pop('templates', self.templates)
        self.print_button = kwargs.pop('print_button', self.print_button)
        if self.onRecordLoaded() is False:
            return False
        self.showTemplate(hideTemplate is not True)
        self.htmlTemplate = None
        self.prepareTemplates()
        self.builder = GnrHtmlBuilder(page_width=self.page_width, page_height=self.page_height,
                                      page_margin_top=self.page_margin_top, page_margin_bottom=self.page_margin_bottom,
                                      page_margin_left=self.page_margin_left, page_margin_right=self.page_margin_right,
                                      page_debug=self.page_debug, print_button=self.print_button,
                                      htmlTemplate=self.htmlTemplate, css_requires=self.get_css_requires(),
                                      showTemplateContent=self.showTemplateContent)
        result = self.createHtml(filepath=self.filepath)
        return result

    def get_css_requires(self):
        return self.css_requires.split(',')

    def prepareTemplates(self):
        """add???"""
        if not self.htmlTemplate:
            self.htmlTemplate = self.templateLoader(self.templates)
        self.page_height = self.page_height or self.htmlTemplate['main.page.height'] or 280
        self.page_width = self.page_width or self.htmlTemplate['main.page.width'] or 200
        self.page_header_height = self.page_header_height or  self.htmlTemplate['layout.top?height'] or 0
        self.page_footer_height = self.page_footer_height or  self.htmlTemplate['layout.bottom?height'] or 0
        self.page_leftbar_width = self.page_leftbar_width or  self.htmlTemplate['layout.left?width'] or 0
        self.page_rightbar_width = self.page_leftbar_width or  self.htmlTemplate['layout.right?width'] or 0
        self.page_margin_top = self.page_margin_top or self.htmlTemplate['main.page.top'] or 0
        self.page_margin_left = self.page_margin_left or self.htmlTemplate['main.page.left'] or 0
        self.page_margin_right = self.page_margin_right or self.htmlTemplate['main.page.right'] or 0
        self.page_margin_bottom = self.page_margin_bottom or self.htmlTemplate['main.page.bottom'] or 0
        
    def toText(self, obj, locale=None, format=None, mask=None, encoding=None, **kwargs):
        """add???
        
        :param obj: add???
        :param locale: add???. Default value is ``None``
        :param format: add???. Default value is ``None``
        :param mask: add???. Default value is ``None``
        :param encoding: The multibyte character encoding you choose. Default value is ``None``
        :returns: add???
        """
        locale = locale or self.locale
        encoding = locale or self.encoding
        return toText(obj, locale=locale, format=format, mask=mask, encoding=encoding, **kwargs)
        
    def createHtml(self, filepath=None):
        """add???
        
        :param filepath: add???. Default value is ``None``
        :returns: add???
        """
        #filepath = filepath or self.filepath
        self.initializeBuilder()
        self.main()
        self.builder.toHtml(filepath=filepath)
        return self.builder.html
        
    def showTemplate(self, value):
        """add???
        
        :param value: add???
        :returns: add???
        """
        self.showTemplateContent = value
        
    def setTemplates(self, templates):
        """add???
        
        :param templates: add???
        :returns: add???
        """
        self.templates = templates
        
    def getTemplates(self, templates):
        """add???
        
        :param templates: add???
        :returns: add???
        """
        return self.templates
        
    def initializeBuilder(self):
        """add???"""
        self.builder.initializeSrc()
        self.body = self.builder.body
        self.getNewPage = self.builder.newPage
        self.builder.styleForLayout()
        
    def getData(self, path, default=None):
        """add???
        
        :param path: add???
        :param default: add???. Default value is ``None``
        :returns: add???
        """
        wildchars = []
        if path[0] in wildchars:
            value = 'not yet implemented'
        else:
            value = self._data.getItem(path, default)
        return value
        
    def setData(self, path, value, **kwargs):
        """add???
        
        :param path: add???
        :param value: add???
        """
        self._data.setItem(path, value, **kwargs)
        
    def onRecordExit(self, recordBag):
        """add???
        
        :param recordBag: add???
        """
        return
        
    def field(self, path, default=None, locale=None,
              format=None, mask=None, root=None, **kwargs):
        """add???
        
        :param path: add???
        :param default: add???. Default value is ``None``
        :param locale: add???. Default value is ``None``
        :param format: add???. Default value is ``None``
        :param mask: add???. Default value is ``None``
        :param root: add???. Default value is ``None``
        :returns: add???
        """
        if root is None:
            root = self._data['record']
        attr = {}
        if isinstance(root, Bag):
            datanode = root.getNode(path)
            if datanode:
                value = datanode.value
                attr = datanode.attr
            else:
                value = default
        else:
            value = root.get(path)
        if value is None:
            value = default
        elif isinstance(value, Bag):
            return value
            
        format = format or attr.get('format')
        mask = mask or attr.get('mask')
        return self.toText(value, locale, format, mask, self.encoding, **kwargs)
        
    def main(self):
        """It can be overridden"""
        if self.htmlContent:
            page = self.getNewPage()
            page.div("%s::HTML" % self.htmlContent)
        else:
            self.mainLoop()
            
    def pageCounter(self, mask=None):
        """add???
        
        :param mask: add???. Default value is ``None``
        """
        mask = mask or '%s/%s'
        
        def getPage(currPage=0):
            result = mask % (currPage + 1 + self.starting_page_number,
                             self.copies[self.copy]['currPage'] + 1 + self.starting_page_number)
            return result
            
        return BagCbResolver(getPage, currPage=self.copies[self.copy]['currPage'])
        
    def copyHeight(self):
        """add???"""
        return (self.page_height - self.page_margin_top - self.page_margin_bottom -\
                self.page_header_height - self.page_footer_height -\
                self.copy_extra_height * (self.copies_per_page - 1)) / self.copies_per_page
                
    def copyWidth(self):
        """add???"""
        return (self.page_width - self.page_margin_left - self.page_margin_right -\
                self.page_leftbar_width - self.page_rightbar_width)
                
    def mainLoop(self):
        """add???"""
        self.copies = []
        self.lastPage = False
        self.defineStandardStyles()
        self.defineCustomStyles()
        self.doc_height = self.copyHeight() #- self.page_header_height - self.page_footer_height
        self.grid_height = self.doc_height - self.calcDocHeaderHeight() - self.doc_footer_height
        self.grid_body_height = self.grid_height - self.grid_header_height - self.grid_footer_height
        for copy in range(self.copies_per_page):
            self.copies.append(dict(grid_body_used=self.grid_height, currPage=-1))
            
        lines = self.getData(self.rows_path)
        
        if lines:
            if isinstance(lines, Bag):
                nodes = lines.getNodes()
            elif hasattr(lines, 'next'):
                nodes = list(lines)
                
            if hasattr(self, 'thermo_wrapper') and self.thermo_kwargs:
                nodes = self.thermo_wrapper(nodes, **self.thermo_kwargs)
                
            for rowDataNode in nodes:
                self.currRowDataNode = rowDataNode
                for copy in range(self.copies_per_page):
                    self.copy = copy
                    rowheight = self.calcRowHeight()
                    availableSpace = self.grid_height - self.copyValue('grid_body_used') -\
                                     self.calcGridHeaderHeight() - self.calcGridFooterHeight()
                    if rowheight > availableSpace:
                        self._newPage()
                    row = self.copyValue('body_grid').row(height=rowheight)
                    self.copies[self.copy]['grid_body_used'] = self.copyValue('grid_body_used') + rowheight
                    self.currColumn = 0
                    self.currRow = row
                    self.prepareRow(row)
                    
            for copy in range(self.copies_per_page):
                self.copy = copy
                self._closePage(True)
                
    def _newPage(self):
        if self.copyValue('currPage') >= 0:
            self._closePage()
        self.copies[self.copy]['currPage'] = self.copyValue('currPage') + 1
        self.copies[self.copy]['grid_body_used'] = 0
        self._createPage()
        self._openPage()
        
    def _get_rowData(self):
        if isinstance(self.currRowDataNode, dict):
            return self.currRowDataNode
        elif self.row_mode == 'attribute':
            return self.currRowDataNode.attr
        else:
            return self.currRowDataNode.value
            
    rowData = property(_get_rowData)
    
    def rowField(self, path=None, **kwargs):
        """add???
        
        :param path: add???. Default value is ``None``
        :returns: add???
        """
        #if self.row_mode=='attribute':
        #    data = self.currRowDataNode.attr
        #else:
        #    data = self.currRowDataNode.value
        return self.field(path, root=self.rowData, **kwargs)
        
    def rowCell(self, field=None, value=None, default=None, locale=None,
                format=None, mask=None, currency=None, **kwargs):
        """add???
        
        :param field: add???. Default value is ``None``
        :param value: add???. Default value is ``None``
        :param default: add???. Default value is ``None``
        :param locale: add???. Default value is ``None``
        :param format: add???. Default value is ``None``
        :param mask: add???. Default value is ``None``
        :param currency: add???. Default value is ``None``
        :returns: add???
        """
        if field:
            if callable(field):
                value = field()
            else:
                value = self.rowField(field, default=default, locale=locale, format=format, mask=mask,
                                      currency=currency)
        if value is not None:
            #if self.lastPage:
            #    print 'last page'
            #    print self.currColumn
            #    print self.grid_col_widths[self.currColumn]
            value = self.toText(value, locale, format, mask, self.encoding)
            self.currRow.cell(value, width=self.grid_col_widths[self.currColumn], overflow='hidden',
                              white_space='nowrap', **kwargs)
        self.currColumn = self.currColumn + 1
        return value

    def _createPage(self):
        curr_copy = self.copies[self.copy]
        if self.copy == 0:
            self.paperPage = self.getNewPage()
        self.page_layout = self.mainLayout(self.paperPage)
        #if self.page_header_height:
        #    curr_copy['page_header'] = self.page_layout.row(height=self.page_header_height,lbl_height=4,lbl_class='caption').cell()
        if self.doc_header_height:
            curr_copy['doc_header'] = self.page_layout.row(height=self.calcDocHeaderHeight(), lbl_height=4,
                                                           lbl_class='caption').cell()
        curr_copy['doc_body'] = self.page_layout.row(height=0, lbl_height=4, lbl_class='caption').cell()
        if self.doc_footer_height:
            curr_copy['doc_footer'] = self.page_layout.row(height=self.doc_footer_height, lbl_height=4,
                                                           lbl_class='caption').cell()
            #if self.page_footer_height:
            #    curr_copy['page_footer'] = self.page_layout.row(height=self.page_footer_height,lbl_height=4,lbl_class='caption').cell()
            
    def mainLayout(self, page):
        """must be overridden
        
        :param page: add???
        """
        pass
        
    def _openPage(self):
        #if self.page_header_height:
        #    self.pageHeader(self.copyValue('page_header')) #makeTop
        if self.doc_header_height:
            self.docHeader(self.copyValue('doc_header'))
        self._docBody(self.copyValue('doc_body'))
        
    def _closePage(self, lastPage=None):
        if lastPage:
            self.lastPage = True
        self.fillBodyGrid()
        footer_height = self.calcGridFooterHeight()
        if footer_height:
            row = self.copyValue('body_grid').row(height=footer_height)
            self.currColumn = 0
            self.currRow = row
            self.gridFooter(row)
        if self.doc_footer_height:
            self.docFooter(self.copyValue('doc_footer'), lastPage=lastPage)
            #if self.page_footer_height:
            #    self.pageFooter(self.copyValue('page_footer'),lastPage=lastPage)
            
    def _docBody(self, body):
        header_height = self.calcGridHeaderHeight()
        grid = self.gridLayout(body)
        if header_height:
            self.gridHeader(grid.row(height=header_height))
        self.copies[self.copy]['body_grid'] = grid
        
    def gridLayout(self, grid):
        """It must be overridden
        
        :param grid: add???
        """
        print 'gridLayout must be overridden'
        
    def gridHeader(self, row):
        """It can be overridden
        
        :param row: add???
        """
        lbl_height = 4
        headers = self.grid_col_headers
        if ':' in headers:
            headers, lbl_height = headers.split(':')
            lbl_height = int(lbl_height)
        for k, lbl in enumerate(self.grid_col_headers.split(',')):
            style = None
            if lbl == '|':
                lbl = ''
                style = 'border-top:0mm;border-bottom:0mm;'
            row.cell(lbl=lbl, lbl_height=lbl_height, width=self.grid_col_widths[k], style=style)
            
    def gridFooter(self, row):
        """It can be overridden
        
        :param row: add???
        """
        print 'gridFooter must be overridden'
        
    def fillBodyGrid(self):
        """add???
        """
        row = self.copyValue('body_grid').row()
        for w in self.grid_col_widths:
            row.cell(width=w)
            
    def copyValue(self, valuename):
        """add???
        
        :param valuename: add???
        """
        return self.copies[self.copy][valuename]
        
    def calcRowHeight(self):
        """override for special needs
        
        :returns: add???
        """
        return self.grid_row_height
        
    def calcGridHeaderHeight(self):
        """override for special needs
        
        :returns: add???
        """
        return self.grid_header_height
        
    def calcGridFooterHeight(self):
        """override for special needs
        
        :returns: add???
        """
        return self.grid_footer_height
        
    def calcDocHeaderHeight(self):
        """override for special needs
        
        :returns: add???
        """
        return self.doc_header_height
        
    def defineCustomStyles(self):
        """override this for custom styles
        
        :returns: add???
        """
        pass
        
    def docFooter(self, footer, lastPage=None):
        """add???
        
        :param footer: add???
        :param lastPage: add???. Default value is ``None``
        """
        pass
        
    def pageFooter(self, footer, lastPage=None):
        """add???
        
        :param footer: add???
        :param lastPage: add???. Default value is ``None``
        """
        pass
        
    def pageHeader(self, header):
        """add???
        
        :param header: add???
        """
        pass
        
    def docHeader(self, header):
        """add???
        
        :param header: add???
        """
        pass
        
    def defineStandardStyles(self):
        """add???
        """
        self.body.style("""
                        .caption{text-align:center;
                                 color:gray;
                                 font-size:8pt;
                                 height:4mm;
                                 line-height:4mm;
                                 font-weight: normal;
                                 }
                        .smallCaption{font-size:7pt;
                                  text-align:left;
                                  color:gray;
                                  text-indent:1mm;
                                  width:auto;
                                  font-weight: normal;
                                  line-height:auto;
                                  line-height:3mm;
                                  height:3mm;""")
                                  
        self.body.style("""
                        .extrasmall {font-size:6pt;text-align:left;line-height:3mm;}
                        .textfield {text-indent:0mm;margin:1mm;line-height:3mm}
                        .dotted_bottom {border-bottom:1px dotted gray;}
                                                
                        .aligned_right{
                            text-align:right;
                            margin-right:1mm;
                        }
                        .aligned_left{
                            text-align:left;
                            margin-left:1mm;
                        }
                        .aligned_center{
                            text-align:center;
                        }
                         """)