facilitating saving info dictionary
authorandy
Sat, 29 Jul 2006 11:33:20 +0000
changeset 2666 a72c25280be2
parent 2665 1b1ff5f0c6cb
child 2667 eaacfc3ce82c
facilitating saving info dictionary
reportlab/pdfbase/pdfdoc.py
reportlab/pdfgen/canvas.py
reportlab/platypus/doctemplate.py
--- a/reportlab/pdfbase/pdfdoc.py	Fri Jul 21 12:45:38 2006 +0000
+++ b/reportlab/pdfbase/pdfdoc.py	Sat Jul 29 11:33:20 2006 +0000
@@ -304,15 +304,38 @@
 
     def setTitle(self, title):
         "embeds in PDF file"
-        self.info.title = title
+        if title is None:
+            self.info.title = '(anonymous)'
+        else:
+            self.info.title = title
+
 
     def setAuthor(self, author):
         "embedded in PDF file"
-        self.info.author = author
+        #allow resetting to clear it
+        if author is None:
+            self.info.author = '(anonymous)'
+        else:
+            self.info.author = author
 
     def setSubject(self, subject):
         "embeds in PDF file"
-        self.info.subject = subject
+
+        #allow resetting to clear it
+        if subject is None:
+            self.info.subject = '(unspecified)'
+        else:
+            self.info.subject = subject
+
+    def setKeywords(self, keywords):
+        "embeds a string containing keywords in PDF file"
+
+        #allow resetting to clear it but ensure it's a string
+        if keywords is None:
+            self.info.keywords = ''
+        else:
+            self.info.keywords = keywords
+
 
     def setDateFormatter(self, dateFormatter):
         self.info._dateFormatter = dateFormatter
@@ -605,6 +628,9 @@
             L = " ".join(L)
         return "<< %s >>" % L
 
+    def copy(self):
+        return PDFDictionary(self.dict)
+    
 # stream filters are objects to support round trip and
 # possibly in the future also support parameters
 class PDFStreamFilterZCompress:
@@ -1308,6 +1334,7 @@
     title = "untitled"
     author = "anonymous"
     subject = "unspecified"
+    keywords = ""
     _dateFormatter = None
 
     def __init__(self):
@@ -1315,7 +1342,7 @@
 
     def digest(self, md5object):
         # add self information to signature
-        for x in (self.title, self.author, self.subject):
+        for x in (self.title, self.author, self.subject, self.keywords):
             md5object.update(str(x))
 
     def format(self, document):
@@ -1325,9 +1352,17 @@
         D["CreationDate"] = PDFDate(invariant=self.invariant,dateFormatter=self._dateFormatter)
         D["Producer"] = PDFString(self.producer)
         D["Subject"] = PDFString(self.subject)
+        D["Keywords"] = PDFString(self.keywords)
+            
         PD = PDFDictionary(D)
         return PD.format(document)
 
+    def copy(self):
+        "shallow copy - useful in pagecatchering"
+        thing = self.__klass__()
+        for (k, v) in self.__dict__.items():
+            setattr(thing, k, v)
+        return thing
 # skipping thumbnails, etc
 
 
--- a/reportlab/pdfgen/canvas.py	Fri Jul 21 12:45:38 2006 +0000
+++ b/reportlab/pdfgen/canvas.py	Sat Jul 29 11:33:20 2006 +0000
@@ -336,6 +336,14 @@
            in the document itself."""
         self._doc.setSubject(subject)
 
+    def setKeywords(self, keywords):
+        """write a list of keywords into the PDF file which shows in document properties.
+        Either submit a single string or a list/tuple"""
+        if type(keywords) in (TupleType, ListType):
+            keywords = ', '.join(keywords)
+        self._doc.setKeywords(keywords)
+        
+
     def pageHasData(self):
         "Info function - app can call it after showPage to see if it needs a save"
         return len(self._code) == 0
--- a/reportlab/platypus/doctemplate.py	Fri Jul 21 12:45:38 2006 +0000
+++ b/reportlab/platypus/doctemplate.py	Sat Jul 29 11:33:20 2006 +0000
@@ -316,6 +316,8 @@
                     'allowSplitting':1,
                     'title':None,
                     'author':None,
+                    'subject':None,
+                    'keywords':[],
                     'invariant':None,
                     'pageCompression':None,
                     '_pageBreakQuick':1,
@@ -675,11 +677,18 @@
                                 pagesize=self.pagesize,
                                 invariant=self.invariant,
                                 pageCompression=self.pageCompression)
+
+        self.canv.setAuthor(self.author)
+        self.canv.setTitle(self.title)
+        self.canv.setSubject(self.subject)
+        self.canv.setKeywords(self.keywords)
+        
         if self._onPage:
             self.canv.setPageCallBack(self._onPage)
         self.handle_documentBegin()
 
     def _endBuild(self):
+        print 'start of doc._endBuild: keywords=', self.canv._doc.info.keywords
         if self._hanging!=[] and self._hanging[-1] is PageBegin:
             del self._hanging[-1]
             self.clean_hanging()
@@ -707,11 +716,18 @@
             self._onProgress('SIZE_EST', len(flowables))
         self._startBuild(filename,canvasmaker)
 
+        #pagecatcher can drag in information from embedded PDFs and we want ours
+        #to take priority, so cache and reapply our own info dictionary after the build.
+        self._savedInfo = self.canv._doc.info
+        handled = 0
         while len(flowables):
             self.clean_hanging()
             try:
                 first = flowables[0]
                 self.handle_flowable(flowables)
+                handled += 1
+
+
             except:
                 #if it has trace info, add it to the traceback message.
                 if hasattr(first, '_traceInfo') and first._traceInfo:
@@ -730,6 +746,9 @@
             if self._onProgress:
                 self._onProgress('PROGRESS',flowableCount - len(flowables))
 
+        #reapply pagecatcher info
+        self.canv._doc.info = self._savedInfo 
+
         self._endBuild()
         if self._onProgress:
             self._onProgress('FINISHED',0)