reportlab/platypus/doctemplate.py
changeset 2950 6c243412b06c
parent 2923 b5c8043382fc
child 2955 cc16265295fb
equal deleted inserted replaced
2948:6864223fb014 2950:6c243412b06c
   202     def __init__(self):
   202     def __init__(self):
   203         pass
   203         pass
   204 
   204 
   205     def frameAction(self,frame):
   205     def frameAction(self,frame):
   206         if not frame._atTop:
   206         if not frame._atTop:
   207             frame._generated_content = [PageBreak()]
   207             frame.add_generated_content(PageBreak())
   208 
   208 
   209 class NextPageTemplate(ActionFlowable):
   209 class NextPageTemplate(ActionFlowable):
   210     """When you get to the next page, use the template specified (change to two column, for example)  """
   210     """When you get to the next page, use the template specified (change to two column, for example)  """
   211     def __init__(self,pt):
   211     def __init__(self,pt):
   212         ActionFlowable.__init__(self,('nextPageTemplate',pt))
   212         ActionFlowable.__init__(self,('nextPageTemplate',pt))
   486 
   486 
   487     def handle_frameEnd(self,resume=0):
   487     def handle_frameEnd(self,resume=0):
   488         ''' Handles the semantics of the end of a frame. This includes the selection of
   488         ''' Handles the semantics of the end of a frame. This includes the selection of
   489             the next frame or if this is the last frame then invoke pageEnd.
   489             the next frame or if this is the last frame then invoke pageEnd.
   490         '''
   490         '''
   491 
       
   492         self._leftExtraIndent = self.frame._leftExtraIndent
   491         self._leftExtraIndent = self.frame._leftExtraIndent
   493         self._rightExtraIndent = self.frame._rightExtraIndent
   492         self._rightExtraIndent = self.frame._rightExtraIndent
   494 
   493 
       
   494         f = self.frame
   495         if hasattr(self,'_nextFrameIndex'):
   495         if hasattr(self,'_nextFrameIndex'):
   496             self.frame = self.pageTemplate.frames[self._nextFrameIndex]
   496             self.frame = self.pageTemplate.frames[self._nextFrameIndex]
   497             self.frame._debug = self._debug
   497             self.frame._debug = self._debug
   498             del self._nextFrameIndex
   498             del self._nextFrameIndex
   499             self.handle_frameBegin(resume)
   499             self.handle_frameBegin(resume)
   500         elif hasattr(self.frame,'lastFrame') or self.frame is self.pageTemplate.frames[-1]:
   500         elif hasattr(f,'lastFrame') or f is self.pageTemplate.frames[-1]:
   501             self.handle_pageEnd()
   501             self.handle_pageEnd()
   502             self.frame = None
   502             self.frame = None
   503         else:
   503         else:
   504             f = self.frame
       
   505             self.frame = self.pageTemplate.frames[self.pageTemplate.frames.index(f) + 1]
   504             self.frame = self.pageTemplate.frames[self.pageTemplate.frames.index(f) + 1]
   506             self.frame._debug = self._debug
   505             self.frame._debug = self._debug
   507             self.handle_frameBegin()
   506             self.handle_frameBegin()
   508 
   507 
   509     def handle_nextPageTemplate(self,pt):
   508     def handle_nextPageTemplate(self,pt):
   539                 raise ValueError("Invalid cycle restart position")
   538                 raise ValueError("Invalid cycle restart position")
   540 
   539 
   541             #ensure we start on the first one
   540             #ensure we start on the first one
   542             self._nextPageTemplateCycle = c.cyclicIterator()
   541             self._nextPageTemplateCycle = c.cyclicIterator()
   543         else:
   542         else:
   544             raise TypeError, "argument pt should be string or integer or list"
   543             raise TypeError("argument pt should be string or integer or list")
   545 
   544 
   546     def handle_nextFrame(self,fx,resume=0):
   545     def handle_nextFrame(self,fx,resume=0):
   547         '''On endFrame change to the frame with name or index fx'''
   546         '''On endFrame change to the frame with name or index fx'''
   548         if type(fx) is StringType:
   547         if type(fx) is StringType:
   549             for f in self.pageTemplate.frames:
   548             for f in self.pageTemplate.frames:
   550                 if f.id == fx:
   549                 if f.id == fx:
   551                     self._nextFrameIndex = self.pageTemplate.frames.index(f)
   550                     self._nextFrameIndex = self.pageTemplate.frames.index(f)
   552                     return
   551                     return
   553             raise ValueError, "can't find frame('%s')"%fx
   552             raise ValueError("can't find frame('%s') in %r(%s) which has frames %r"%(fx,self.pageTemplate,self.pageTemplate.id,[(f,f.id) for f in self.pageTemplate.frames]))
   554         elif type(fx) is IntType:
   553         elif type(fx) is IntType:
   555             self._nextFrameIndex = fx
   554             self._nextFrameIndex = fx
   556         else:
   555         else:
   557             raise TypeError, "argument fx should be string or integer"
   556             raise TypeError, "argument fx should be string or integer"
   558 
   557 
   559     def handle_currentFrame(self,fx,resume=0):
   558     def handle_currentFrame(self,fx,resume=0):
   560         '''change to the frame with name or index fx'''
   559         '''change to the frame with name or index fx'''
       
   560 
   561         self.handle_nextFrame(fx,resume)
   561         self.handle_nextFrame(fx,resume)
   562         self.handle_frameEnd(resume)
   562         self.handle_frameEnd(resume)
   563 
   563 
   564     def handle_breakBefore(self, flowables):
   564     def handle_breakBefore(self, flowables):
   565         '''preprocessing step to allow pageBreakBefore and frameBreakBefore attributes'''
   565         '''preprocessing step to allow pageBreakBefore and frameBreakBefore attributes'''
   607         try:
   607         try:
   608             return f.identity(maxLen)
   608             return f.identity(maxLen)
   609         finally:
   609         finally:
   610             if frame: del f._frame
   610             if frame: del f._frame
   611 
   611 
       
   612     def _addGeneratedContent(self,flowables,frame):
       
   613         S = getattr(frame,'_generated_content',None)
       
   614         if S:
       
   615             for i,f in enumerate(S):
       
   616                 flowables.insert(i,f)
       
   617             del frame._generated_content
       
   618 
   612     def handle_flowable(self,flowables):
   619     def handle_flowable(self,flowables):
   613         '''try to handle one flowable from the front of list flowables.'''
   620         '''try to handle one flowable from the front of list flowables.'''
   614 
   621 
   615         #allow document a chance to look at, modify or ignore
   622         #allow document a chance to look at, modify or ignore
   616         #the object(s) about to be processed
   623         #the object(s) about to be processed
   632         elif isinstance(f,ActionFlowable):
   639         elif isinstance(f,ActionFlowable):
   633             f.apply(self)
   640             f.apply(self)
   634             self.afterFlowable(f)
   641             self.afterFlowable(f)
   635         else:
   642         else:
   636             frame = self.frame
   643             frame = self.frame
       
   644             canv = self.canv
   637             #try to fit it then draw it
   645             #try to fit it then draw it
   638             if frame.add(f, self.canv, trySplit=self.allowSplitting):
   646             if frame.add(f, canv, trySplit=self.allowSplitting):
   639                 if not isinstance(f,FrameActionFlowable):
   647                 if not isinstance(f,FrameActionFlowable):
   640                     self._curPageFlowableCount += 1
   648                     self._curPageFlowableCount += 1
   641                     self.afterFlowable(f)
   649                     self.afterFlowable(f)
   642                 else:
   650                 self._addGeneratedContent(flowables,frame)
   643                     S = getattr(frame,'_generated_content',None)
       
   644                     if S:
       
   645                         for i,f in enumerate(S):
       
   646                             flowables.insert(i,f)
       
   647                         del frame._generated_content
       
   648             else:
   651             else:
   649                 if self.allowSplitting:
   652                 if self.allowSplitting:
   650                     # see if this is a splittable thing
   653                     # see if this is a splittable thing
   651                     S = frame.split(f,self.canv)
   654                     S = frame.split(f,canv)
   652                     n = len(S)
   655                     n = len(S)
   653                 else:
   656                 else:
   654                     n = 0
   657                     n = 0
   655                 if n:
   658                 if n:
   656                     if not isinstance(S[0],(PageBreak,SlowPageBreak,ActionFlowable)):
   659                     if not isinstance(S[0],(PageBreak,SlowPageBreak,ActionFlowable)):
   657                         if frame.add(S[0], self.canv, trySplit=0):
   660                         if frame.add(S[0], canv, trySplit=0):
   658                             self._curPageFlowableCount += 1
   661                             self._curPageFlowableCount += 1
   659                             self.afterFlowable(S[0])
   662                             self.afterFlowable(S[0])
       
   663                             self._addGeneratedContent(flowables,frame)
   660                         else:
   664                         else:
   661                             ident = "Splitting error(n==%d) on page %d in\n%s" % (n,self.page,self._fIdent(f,30,frame))
   665                             ident = "Splitting error(n==%d) on page %d in\n%s" % (n,self.page,self._fIdent(f,60,frame))
   662                             #leave to keep apart from the raise
   666                             #leave to keep apart from the raise
   663                             raise LayoutError(ident)
   667                             raise LayoutError(ident)
   664                         del S[0]
   668                         del S[0]
   665                     for i,f in enumerate(S):
   669                     for i,f in enumerate(S):
   666                         flowables.insert(i,f)   # put split flowables back on the list
   670                         flowables.insert(i,f)   # put split flowables back on the list
   667                 else:
   671                 else:
   668                     if hasattr(f,'_postponed'):
   672                     if hasattr(f,'_postponed'):
   669                         ident = "Flowable %s too large on page %d" % (self._fIdent(f,30,frame), self.page)
   673                         ident = "Flowable %s too large on page %d" % (self._fIdent(f,60,frame), self.page)
   670                         #leave to keep apart from the raise
   674                         #leave to keep apart from the raise
   671                         raise LayoutError(ident)
   675                         raise LayoutError(ident)
   672                     # this ought to be cleared when they are finally drawn!
   676                     # this ought to be cleared when they are finally drawn!
   673                     f._postponed = 1
   677                     f._postponed = 1
   674                     flowables.insert(0,f)           # put the flowable back
   678                     flowables.insert(0,f)           # put the flowable back
   733             self._onProgress('SIZE_EST', len(flowables))
   737             self._onProgress('SIZE_EST', len(flowables))
   734         self._startBuild(filename,canvasmaker)
   738         self._startBuild(filename,canvasmaker)
   735 
   739 
   736         #pagecatcher can drag in information from embedded PDFs and we want ours
   740         #pagecatcher can drag in information from embedded PDFs and we want ours
   737         #to take priority, so cache and reapply our own info dictionary after the build.
   741         #to take priority, so cache and reapply our own info dictionary after the build.
   738         self._savedInfo = self.canv._doc.info
   742         canv = self.canv
       
   743         self._savedInfo = canv._doc.info
   739         handled = 0
   744         handled = 0
   740         while len(flowables):
   745 
   741             self.clean_hanging()
   746         try:
   742             try:
   747             canv._doctemplate = self
   743                 first = flowables[0]
   748             while len(flowables):
   744                 self.handle_flowable(flowables)
   749                 self.clean_hanging()
   745                 handled += 1
   750                 try:
   746             except:
   751                     first = flowables[0]
   747                 #if it has trace info, add it to the traceback message.
   752                     self.handle_flowable(flowables)
   748                 if hasattr(first, '_traceInfo') and first._traceInfo:
   753                     handled += 1
   749                     exc = sys.exc_info()[1]
   754                 except:
   750                     args = list(exc.args)
   755                     #if it has trace info, add it to the traceback message.
   751                     tr = first._traceInfo
   756                     if hasattr(first, '_traceInfo') and first._traceInfo:
   752                     args[0] += '\n(srcFile %s, line %d char %d to line %d char %d)' % (
   757                         exc = sys.exc_info()[1]
   753                         tr.srcFile,
   758                         args = list(exc.args)
   754                         tr.startLineNo,
   759                         tr = first._traceInfo
   755                         tr.startLinePos,
   760                         args[0] += '\n(srcFile %s, line %d char %d to line %d char %d)' % (
   756                         tr.endLineNo,
   761                             tr.srcFile,
   757                         tr.endLinePos
   762                             tr.startLineNo,
   758                         )
   763                             tr.startLinePos,
   759                     exc.args = tuple(args)
   764                             tr.endLineNo,
   760                 raise
   765                             tr.endLinePos
   761             if self._onProgress:
   766                             )
   762                 self._onProgress('PROGRESS',flowableCount - len(flowables))
   767                         exc.args = tuple(args)
       
   768                     raise
       
   769                 if self._onProgress:
       
   770                     self._onProgress('PROGRESS',flowableCount - len(flowables))
       
   771         finally:
       
   772             del canv._doctemplate
       
   773 
   763 
   774 
   764         #reapply pagecatcher info
   775         #reapply pagecatcher info
   765         self.canv._doc.info = self._savedInfo
   776         canv._doc.info = self._savedInfo
   766 
   777 
   767         self._endBuild()
   778         self._endBuild()
   768         if self._onProgress:
   779         if self._onProgress:
   769             self._onProgress('FINISHED',0)
   780             self._onProgress('FINISHED',0)
   770 
   781