Commit 7ead3ad4 authored by Jean-Paul Smets's avatar Jean-Paul Smets

Initial fix of coding style. Implemented dynamic stylesheets.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@12806 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 683b8ecf
...@@ -42,9 +42,9 @@ from AccessControl import ClassSecurityInfo ...@@ -42,9 +42,9 @@ from AccessControl import ClassSecurityInfo
from OOoUtils import OOoBuilder from OOoUtils import OOoBuilder
from zipfile import ZipFile, ZIP_DEFLATED from zipfile import ZipFile, ZIP_DEFLATED
try: try:
from cStringIO import StringIO from cStringIO import StringIO
except ImportError: except ImportError:
from StringIO import StringIO from StringIO import StringIO
import re import re
import itertools import itertools
import xmlrpclib import xmlrpclib
...@@ -52,222 +52,224 @@ import xmlrpclib ...@@ -52,222 +52,224 @@ import xmlrpclib
from zLOG import LOG from zLOG import LOG
try: try:
from webdav.Lockable import ResourceLockedError from webdav.Lockable import ResourceLockedError
from webdav.WriteLockInterface import WriteLockInterface from webdav.WriteLockInterface import WriteLockInterface
SUPPORTS_WEBDAV_LOCKS = 1 SUPPORTS_WEBDAV_LOCKS = 1
except ImportError: except ImportError:
SUPPORTS_WEBDAV_LOCKS = 0 SUPPORTS_WEBDAV_LOCKS = 0
# Constructors # Constructors
manage_addOOoTemplate = DTMLFile("dtml/OOoTemplate_add", globals()) manage_addOOoTemplate = DTMLFile("dtml/OOoTemplate_add", globals())
def addOOoTemplate(self, id, title="", REQUEST=None): def addOOoTemplate(self, id, title="", REQUEST=None):
"""Add OOo template to folder. """Add OOo template to folder.
id -- the id of the new OOo template to add id -- the id of the new OOo template to add
title -- the title of the OOo to add title -- the title of the OOo to add
Result -- empty string Result -- empty string
""" """
# add actual object # add actual object
id = self._setObject(id, OOoTemplate(id, title)) id = self._setObject(id, OOoTemplate(id, title))
file = REQUEST.form.get('file') file = REQUEST.form.get('file')
if file.filename: if file.filename:
# Get the template in the associated context and upload the file # Get the template in the associated context and upload the file
getattr(self,id).pt_upload(REQUEST, file) getattr(self,id).pt_upload(REQUEST, file)
# respond to the add_and_edit button if necessary # respond to the add_and_edit button if necessary
add_and_edit(self, id, REQUEST) add_and_edit(self, id, REQUEST)
return '' return ''
def add_and_edit(self, id, REQUEST): def add_and_edit(self, id, REQUEST):
"""Helper method to point to the object's management screen if """Helper method to point to the object's management screen if
'Add and Edit' button is pressed. 'Add and Edit' button is pressed.
id -- id of the object we just added id -- id of the object we just added
""" """
if REQUEST is None: if REQUEST is None:
return return
try: try:
u = self.DestinationURL() u = self.DestinationURL()
except AttributeError: except AttributeError:
u = REQUEST['URL1'] u = REQUEST['URL1']
if REQUEST['submit'] == " Add and Edit ": if REQUEST['submit'] == " Add and Edit ":
u = "%s/%s" % (u, quote(id)) u = "%s/%s" % (u, quote(id))
REQUEST.RESPONSE.redirect(u+'/manage_main') REQUEST.RESPONSE.redirect(u+'/manage_main')
class OOoTemplate(ZopePageTemplate): class OOoTemplate(ZopePageTemplate):
"""
A page template which is able to embed and OpenOffice
file (zip archive) and replace content.xml at render time
with XML dynamically generated through TAL/TALES/METAL expressions
TODO:
- find a way to embed TALES in OOo documents in such
way that editing with OOo does not destroy TAL/TALES
- add preprocessing option to handle explicit macros in
OOo in any language. Include debugging options in this case
(on preprocessed source rather than pure source)
"""
meta_type = "ERP5 OOo Template"
icon = "www/OOo.png"
# NOTE: 100 is just pure random starting number
# it won't influence the code at all
document_counter = itertools.count(100)
# Every linked OLE document is in a directory starting with 'Obj'
_OLE_directory_prefix = 'Obj'
# every OOo document have a content-type starting like this
_OOo_content_type_root = 'application/vnd.sun.xml.'
# Declarative Security
security = ClassSecurityInfo()
# Declarative properties
property_sheets = ( PropertySheet.Base
, PropertySheet.SimpleItem)
# Constructors
constructors = (manage_addOOoTemplate, addOOoTemplate)
# Default Attributes
ooo_stylesheet = 'Base_getODTStyleSheet'
# Default content type
#content_type = 'application/vnd.sun.xml.writer' # Writer type by default
content_type = 'text/html' # This is the only for now to produce valid XML
# Management interface
manage_options = ( ZopePageTemplate.manage_options +
(
{'label':'Stylesheet Setting', 'action':'formSettings',
'help':('ERPForm', 'pdfStylesheet.txt')},
)
)
security.declareProtected('View management screens', 'formSettings')
formSettings = PageTemplateFile('www/formSettings', globals(),
__name__='formSettings')
formSettings._owner = None
def __init__(self,*args,**kw):
ZopePageTemplate.__init__(self,*args,**kw)
# we store the attachments of the uploaded document
self.OLE_documents_zipstring = None
def pt_upload(self, REQUEST, file=''):
"""Replace the document with the text in file."""
if SUPPORTS_WEBDAV_LOCKS and self.wl_isLocked():
raise ResourceLockedError, "File is locked via WebDAV"
if type(file) is not StringType:
if not file: raise ValueError, 'File not specified'
file = file.read()
if file.startswith("PK") : # FIXME: this condition is probably not enough
# this is a OOo zip file, extract the content
builder = OOoBuilder(file)
attached_files_list = [n for n in builder.getNameList()
if n.startswith(self._OLE_directory_prefix)
or n.startswith('Pictures')
or n == 'META-INF/manifest.xml' ]
# destroy a possibly pre-existing OLE document set
if self.OLE_documents_zipstring:
self.OLE_documents_zipstring = None
# create a zip archive and store it
if attached_files_list:
memory_file = StringIO()
try:
zf = ZipFile(memory_file, mode='w', compression=ZIP_DEFLATED)
except RuntimeError:
zf = ZipFile(memory_file, mode='w')
for attached_file in attached_files_list:
zf.writestr(attached_file, builder.extract(attached_file) )
zf.close()
memory_file.seek(0)
self.OLE_documents_zipstring = memory_file.read()
self.content_type = builder.getMimeType()
file = builder.prepareContentXml()
return ZopePageTemplate.pt_upload(self, REQUEST, file)
security.declareProtected('Change Page Templates', 'doSettings')
def doSettings(self, REQUEST, title, ooo_stylesheet):
""" """
A page template which is able to embed and OpenOffice Change title and ooo_stylesheet.
file (zip archive) and replace content.xml at render time
with XML dynamically generated through TAL/TALES/METAL expressions
TODO:
- find a way to embed TALES in OOo documents in such
way that editing woth OOo does not destroy TAL/TALES
- add preprocessing option to handle explicit macros in
OOo in any language. Include debugging options in this case
(on preprocessed source rather than pure source)
""" """
meta_type = "ERP5 OOo Template" if SUPPORTS_WEBDAV_LOCKS and self.wl_isLocked():
icon = "www/OOo.png" raise ResourceLockedError, "File is locked via WebDAV"
self.ooo_stylesheet = ooo_stylesheet
# NOTE: 100 is just pure random starting number self.pt_setTitle(title)
# it won't influence the code at all #REQUEST.set('text', self.read()) # May not equal 'text'!
document_counter = itertools.count(100) message = "Saved changes."
# Every linked OLE document is in a directory starting with 'Obj' if getattr(self, '_v_warnings', None):
_OLE_directory_prefix = 'Obj' message = ("<strong>Warning:</strong> <i>%s</i>"
# every OOo document have a content-type starting like this % '<br>'.join(self._v_warnings))
_OOo_content_type_root = 'application/vnd.sun.xml.' return self.formSettings(manage_tabs_message=message)
# Declarative Security def _resolvePath(self, path):
security = ClassSecurityInfo() return self.getPortalObject().unrestrictedTraverse(path)
# Declarative properties def renderIncludes(self, here, text, sub_document=None):
property_sheets = ( PropertySheet.Base attached_files_dict = {}
, PropertySheet.SimpleItem) arguments_re = re.compile('(\w+)\s*=\s*"(.*?)"\s*',re.DOTALL)
# Constructors def getLengthInfos( opts_dict, opts_names ):
constructors = (manage_addOOoTemplate, addOOoTemplate) ret = []
for opt_name in opts_names:
# Default Attributes try:
ooo_stylesheet = 'default_ooo_template' val = opts_dict[opt_name]
if val.endswith('cm'):
# Default content type val = val[:-2]
#content_type = 'application/vnd.sun.xml.writer' # Writer type by default val = float( val )
content_type = 'text/html' # This is the only for now to produce valid XML except (ValueError, KeyError):
val = None
# Management interface ret.append(val)
manage_options = ( ZopePageTemplate.manage_options + return ret
(
{'label':'Stylesheet Setting', 'action':'formSettings', def replaceIncludes(match):
'help':('ERPForm', 'pdfStylesheet.txt')}, options_dict = dict( style="fr1", x="0cm", y="0cm" )
) options_dict.update( dict(arguments_re.findall( match.group(1) )) )
) document = self._resolvePath( options_dict['path'] )
document_text = document.read()
if 'type' not in options_dict:
options_dict['type'] = document.content_type
else: # type passed in short form as an attribute
options_dict['type'] = self._OOo_content_type_root + options_dict['type']
w, h, x, y = getLengthInfos( options_dict , ('width', 'height', 'x', 'y') )
# Set defaults
if w is None:
w = 10.0
if h is None:
h = 10.0
if x is None:
x = 0.0
if y is None:
y = 0.0
actual_idx = self.document_counter.next()
dir_name = '%s%d'%(self._OLE_directory_prefix,actual_idx)
if sub_document: # sub-document means sub-directory
dir_name = sub_document + '/' + dir_name
security.declareProtected('View management screens', 'formSettings') try:
formSettings = PageTemplateFile('www/formSettings', globals(), ooo_stylesheet = getattr(here, document.ooo_stylesheet)
__name__='formSettings') # If style is dynamic, call it
formSettings._owner = None if callable(ooo_stylesheet):
ooo_stylesheet = ooo_stylesheet()
temp_builder = OOoBuilder(ooo_stylesheet)
stylesheet = temp_builder.extract('styles.xml')
except AttributeError:
stylesheet = None
def __init__(self,*args,**kw): sub_attached_files_dict = {}
ZopePageTemplate.__init__(self,*args,**kw) if 'office:include' in document_text: # small optimisation to avoid recursion if possible
# we store the attachments of the uploaded document (document_text, sub_attached_files_dict ) = self.renderIncludes(document_text, dir_name)
self.OLE_documents_zipstring = None
def pt_upload(self, REQUEST, file=''): # View* = writer
"""Replace the document with the text in file.""" # Visible* = calc
if SUPPORTS_WEBDAV_LOCKS and self.wl_isLocked(): settings_text = """<?xml version="1.0" encoding="UTF-8"?>
raise ResourceLockedError, "File is locked via WebDAV"
if type(file) is not StringType:
if not file: raise ValueError, 'File not specified'
file = file.read()
if file.startswith("PK") : # FIXME: this condition is probably not enough
# this is a OOo zip file, extract the content
builder = OOoBuilder(file)
attached_files_list = [n for n in builder.getNameList()
if n.startswith(self._OLE_directory_prefix)
or n.startswith('Pictures')
or n == 'META-INF/manifest.xml' ]
# destroy a possibly pre-existing OLE document set
if self.OLE_documents_zipstring:
self.OLE_documents_zipstring = None
# create a zip archive and store it
if attached_files_list:
memory_file = StringIO()
try:
zf = ZipFile(memory_file, mode='w', compression=ZIP_DEFLATED)
except RuntimeError:
zf = ZipFile(memory_file, mode='w')
for attached_file in attached_files_list:
zf.writestr(attached_file, builder.extract(attached_file) )
zf.close()
memory_file.seek(0)
self.OLE_documents_zipstring = memory_file.read()
self.content_type = builder.getMimeType()
file = builder.prepareContentXml()
return ZopePageTemplate.pt_upload(self, REQUEST, file)
security.declareProtected('Change Page Templates', 'doSettings')
def doSettings(self, REQUEST, title, ooo_stylesheet):
"""
Change title and ooo_stylesheet.
"""
if SUPPORTS_WEBDAV_LOCKS and self.wl_isLocked():
raise ResourceLockedError, "File is locked via WebDAV"
self.ooo_stylesheet = ooo_stylesheet
self.pt_setTitle(title)
#REQUEST.set('text', self.read()) # May not equal 'text'!
message = "Saved changes."
if getattr(self, '_v_warnings', None):
message = ("<strong>Warning:</strong> <i>%s</i>"
% '<br>'.join(self._v_warnings))
return self.formSettings(manage_tabs_message=message)
def _resolvePath(self, path):
return self.getPortalObject().unrestrictedTraverse(path)
def renderIncludes(self, text, sub_document=None):
attached_files_dict = {}
arguments_re = re.compile('(\w+)\s*=\s*"(.*?)"\s*',re.DOTALL)
def getLengthInfos( opts_dict, opts_names ):
ret = []
for opt_name in opts_names:
try:
val = opts_dict[opt_name]
if val.endswith('cm'):
val = val[:-2]
val = float( val )
except (ValueError, KeyError):
val = None
ret.append(val)
return ret
def replaceIncludes(match):
options_dict = dict( style="fr1", x="0cm", y="0cm" )
options_dict.update( dict(arguments_re.findall( match.group(1) )) )
document = self._resolvePath( options_dict['path'] )
document_text = document.read()
if 'type' not in options_dict:
options_dict['type'] = document.content_type
else: # type passed in short form as an attribute
options_dict['type'] = self._OOo_content_type_root + options_dict['type']
w, h, x, y = getLengthInfos( options_dict , ('width', 'height', 'x', 'y') )
# Set defaults
if w is None:
w = 10.0
if h is None:
h = 10.0
if x is None:
x = 0.0
if y is None:
y = 0.0
actual_idx = self.document_counter.next()
dir_name = '%s%d'%(self._OLE_directory_prefix,actual_idx)
if sub_document: # sub-document means sub-directory
dir_name = sub_document+'/'+dir_name
try:
temp_builder = OOoBuilder(getattr(document,document.ooo_stylesheet))
stylesheet = temp_builder.extract('styles.xml')
except AttributeError:
stylesheet = None
sub_attached_files_dict = {}
if 'office:include' in document_text: # small optimisation to avoid recursion if possible
(document_text, sub_attached_files_dict ) = self.renderIncludes(document_text, dir_name)
# View* = writer
# Visible* = calc
settings_text = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE office:document-settings PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "office.dtd"> <!DOCTYPE office:document-settings PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "office.dtd">
<office:document-settings xmlns:office="http://openoffice.org/2000/office" <office:document-settings xmlns:office="http://openoffice.org/2000/office"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
...@@ -285,259 +287,264 @@ xmlns:config="http://openoffice.org/2001/config" office:version="1.0"> ...@@ -285,259 +287,264 @@ xmlns:config="http://openoffice.org/2001/config" office:version="1.0">
</config:config-item-set> </config:config-item-set>
</office:settings> </office:settings>
</office:document-settings>"""%dict( w=int(w*1000) , h=int(h*1000) ) # convert from 10^-2 (centimeters) to 10^-5 </office:document-settings>"""%dict( w=int(w*1000) , h=int(h*1000) ) # convert from 10^-2 (centimeters) to 10^-5
attached_files_dict[dir_name] = dict(document = document_text, attached_files_dict[dir_name] = dict(document = document_text,
doc_type = options_dict['type'], stylesheet = stylesheet ) doc_type = options_dict['type'], stylesheet = stylesheet )
attached_files_dict[dir_name+'/settings.xml'] = dict( document = settings_text, attached_files_dict[dir_name+'/settings.xml'] = dict( document = settings_text,
doc_type = 'text/xml' ) doc_type = 'text/xml' )
attached_files_dict.update(sub_attached_files_dict ) attached_files_dict.update(sub_attached_files_dict )
# add a paragraph with the OLE document in it # add a paragraph with the OLE document in it
# The dir_name is relative here, extract the last path component # The dir_name is relative here, extract the last path component
replacement = """ replacement = """
<draw:object draw:style-name="%s" draw:name="ERP5IncludedObject%d" <draw:object draw:style-name="%s" draw:name="ERP5IncludedObject%d"
text:anchor-type="paragraph" svg:x="%.3fcm" svg:y="%.3fcm" text:anchor-type="paragraph" svg:x="%.3fcm" svg:y="%.3fcm"
svg:width="%.3fcm" svg:height="%.3fcm" xlink:href="#./%s svg:width="%.3fcm" svg:height="%.3fcm" xlink:href="#./%s
" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/> " xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/>
"""%(options_dict['style'], actual_idx, x, y, w, h, dir_name.split('/')[-1]) """%(options_dict['style'], actual_idx, x, y, w, h, dir_name.split('/')[-1])
if not self.content_type.endswith('draw'): if not self.content_type.endswith('draw'):
replacement = '<text:p text:style-name="Standard">'+replacement+'</text:p>' replacement = '<text:p text:style-name="Standard">'+replacement+'</text:p>'
return replacement return replacement
def replaceIncludesImg(match): def replaceIncludesImg(match):
options_dict = dict( x='0cm', y='0cm', style="fr1" ) options_dict = dict( x='0cm', y='0cm', style="fr1" )
options_dict.update( dict(arguments_re.findall( match.group(1) )) ) options_dict.update( dict(arguments_re.findall( match.group(1) )) )
picture = self._resolvePath( options_dict['path'] ) picture = self._resolvePath( options_dict['path'] )
# "standard" filetype == Image or File , for ERP objects the # "standard" filetype == Image or File , for ERP objects the
# manipulations are different # manipulations are different
is_standard_filetype = True is_standard_filetype = True
if not hasattr(picture,'data') or callable(picture.content_type): if not hasattr(picture,'data') or callable(picture.content_type):
is_standard_filetype = False is_standard_filetype = False
if is_standard_filetype: if is_standard_filetype:
picture_data = picture.data picture_data = picture.data
else: else:
picture_data = picture.Base_download() picture_data = picture.Base_download()
# fetch the content-type of the picture (generally guessed by zope) # fetch the content-type of the picture (generally guessed by zope)
if 'type' not in options_dict: if 'type' not in options_dict:
if is_standard_filetype: if is_standard_filetype:
options_dict['type'] = picture.content_type options_dict['type'] = picture.content_type
else: else:
options_dict['type'] = picture.content_type() options_dict['type'] = picture.content_type()
if '/' not in options_dict['type']: if '/' not in options_dict['type']:
options_dict['type'] = 'image/' + options_dict['type'] options_dict['type'] = 'image/' + options_dict['type']
w, h, maxwidth, maxheight = getLengthInfos( options_dict, ('width','height','maxwidth','maxheight') ) w, h, maxwidth, maxheight = getLengthInfos( options_dict, ('width','height','maxwidth','maxheight') )
try:
aspect_ratio = float(picture.width) / float(picture.height)
except TypeError:
aspect_ratio = float(picture.width()) / float(picture.height())
# fix a default value and correct the aspect
if h is None:
if w is None:
w = 10.0
h = w / aspect_ratio
elif w is None:
w = h * aspect_ratio
# picture is too large
if maxwidth and maxwidth < w:
w = maxwidth
h = w / aspect_ratio
if maxheight and maxheight < h:
h = maxheight
w = h * aspect_ratio
actual_idx = self.document_counter.next()
pic_name = 'Pictures/picture%d.%s'%(actual_idx, options_dict['type'].split('/')[-1])
if sub_document: # sub-document means sub-directory
pic_name = sub_document+'/'+pic_name
attached_files_dict[pic_name] = dict(
document = picture_data,
doc_type = options_dict['type']
)
# XXX: Pictures directory not managed (seems facultative)
# <manifest:file-entry manifest:media-type="" manifest:full-path="ObjBFE4F50D/Pictures/"/>
replacement = """<draw:image draw:style-name="%s" draw:name="ERP5Image%d"
text:anchor-type="paragraph" svg:x="%s" svg:y="%s"
svg:width="%.3fcm" svg:height="%.3fcm" xlink:href="#Pictures/%s"
xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/>
"""%(options_dict['style'], actual_idx,
options_dict['x'], options_dict['y'],
w, h,
pic_name.split('/')[-1] )
if not ( self.content_type.endswith('draw') or
self.content_type.endswith('presentation') or
self.content_type.endswith('writer') or
self.content_type.endswith('text') ):
replacement = '<text:p text:style-name="Standard">'+replacement+'</text:p>'
return replacement
# NOTE: (?s) at the end is for including '\n' when matching '.'
# It's an equivalent to DOTALL option passing (but sub can't get options parameter)
text = re.sub('<\s*office:include_img\s+(.*?)\s*/\s*>(?s)', replaceIncludesImg, text)
text = re.sub('<\s*office:include\s+(.*?)\s*/\s*>(?s)', replaceIncludes, text)
return (text, attached_files_dict)
# Proxy method to PageTemplate
def pt_render(self, source=0, extra_context={}):
# Get request
request = extra_context.get('REQUEST', None)
if not request:
request = get_request()
# Retrieve master document
ooo_document = getattr(self, self.ooo_stylesheet)
# Create a new builder instance
ooo_builder = OOoBuilder(ooo_document)
# Pass builder instance as extra_context
extra_context['ooo_builder'] = ooo_builder
# And render page template
doc_xml = ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context)
# Replace the includes
(doc_xml,attachments_dict) = self.renderIncludes(doc_xml)
try: try:
default_styles_text = ooo_builder.extract('styles.xml') aspect_ratio = float(picture.width) / float(picture.height)
except AttributeError: except TypeError:
default_styles_text = None aspect_ratio = float(picture.width()) / float(picture.height())
# Add the associated files # fix a default value and correct the aspect
for dir_name, document_dict in attachments_dict.iteritems(): if h is None:
# Special case : the document is an OOo one if w is None:
if document_dict['doc_type'].startswith(self._OOo_content_type_root): w = 10.0
ooo_builder.addFileEntry(full_path = dir_name, h = w / aspect_ratio
media_type = document_dict['doc_type'] ) elif w is None:
ooo_builder.addFileEntry(full_path = dir_name+'/content.xml', w = h * aspect_ratio
media_type = 'text/xml',content = document_dict['document'] ) # picture is too large
styles_text = default_styles_text if maxwidth and maxwidth < w:
if document_dict.has_key('stylesheet') and document_dict['stylesheet']: w = maxwidth
styles_text = document_dict['stylesheet'] h = w / aspect_ratio
if styles_text: if maxheight and maxheight < h:
ooo_builder.addFileEntry(full_path = dir_name+'/styles.xml', h = maxheight
media_type = 'text/xml',content = styles_text ) w = h * aspect_ratio
else: # Generic case
ooo_builder.addFileEntry(full_path=dir_name, actual_idx = self.document_counter.next()
media_type=document_dict['doc_type'], content = document_dict['document'] ) pic_name = 'Pictures/picture%d.%s'%(actual_idx, options_dict['type'].split('/')[-1])
# Get request and batch_mode if sub_document: # sub-document means sub-directory
batch_mode = extra_context.get('batch_mode', 0) pic_name = sub_document+'/'+pic_name
# Debug mode attached_files_dict[pic_name] = dict(
if request.get('debug',0): document = picture_data,
return doc_xml doc_type = options_dict['type']
)
# Replace content.xml in master openoffice template # XXX: Pictures directory not managed (seems facultative)
ooo_builder.replace('content.xml', doc_xml) # <manifest:file-entry manifest:media-type="" manifest:full-path="ObjBFE4F50D/Pictures/"/>
replacement = """<draw:image draw:style-name="%s" draw:name="ERP5Image%d"
# Old templates correction text:anchor-type="paragraph" svg:x="%s" svg:y="%s"
try: svg:width="%.3fcm" svg:height="%.3fcm" xlink:href="#Pictures/%s"
self.OLE_documents_zipstring xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/>
except AttributeError: """ % (options_dict['style'], actual_idx,
self.OLE_documents_zipstring = None options_dict['x'], options_dict['y'],
w, h,
pic_name.split('/')[-1] )
if not (self.content_type.endswith('draw') or
self.content_type.endswith('presentation') or
self.content_type.endswith('writer') or
self.content_type.endswith('text')):
replacement = '<text:p text:style-name="Standard">'+replacement+'</text:p>'
return replacement
# NOTE: (?s) at the end is for including '\n' when matching '.'
# It's an equivalent to DOTALL option passing (but sub can't get options parameter)
text = re.sub('<\s*office:include_img\s+(.*?)\s*/\s*>(?s)', replaceIncludesImg, text)
text = re.sub('<\s*office:include\s+(.*?)\s*/\s*>(?s)', replaceIncludes, text)
return (text, attached_files_dict)
# Proxy method to PageTemplate
def pt_render(self, source=0, extra_context={}):
# Get request
request = extra_context.get('REQUEST', None)
if not request:
request = get_request()
# Get parent object (the one to render this template on)
here = getattr(self, 'aq_parent', None)
if here is None:
# This is a system error
raise ValueError, 'Can not render a template without a parent acquisition context'
# Retrieve master document
ooo_document = getattr(here, self.ooo_stylesheet)
# If style is dynamic, call it
if callable(ooo_stylesheet):
ooo_stylesheet = ooo_stylesheet()
# Create a new builder instance
ooo_builder = OOoBuilder(ooo_document)
# Pass builder instance as extra_context
extra_context['ooo_builder'] = ooo_builder
# And render page template
doc_xml = ZopePageTemplate.pt_render(self, source=source, extra_context=extra_context)
# Replace the includes
(doc_xml,attachments_dict) = self.renderIncludes(here, doc_xml)
# If the file has embedded OLE documents, restore it try:
if self.OLE_documents_zipstring: default_styles_text = ooo_builder.extract('styles.xml')
additional_builder = OOoBuilder( self.OLE_documents_zipstring ) except AttributeError:
for name in additional_builder.getNameList(): default_styles_text = None
ooo_builder.replace(name, additional_builder.extract(name) ) # Add the associated files
for dir_name, document_dict in attachments_dict.iteritems():
# Update the META informations # Special case : the document is an OOo one
ooo_builder.updateManifest() if document_dict['doc_type'].startswith(self._OOo_content_type_root):
ooo_builder.addFileEntry(full_path = dir_name,
# Produce final result media_type = document_dict['doc_type'] )
ooo = ooo_builder.render(self.title or self.id) ooo_builder.addFileEntry(full_path = dir_name+'/content.xml',
media_type = 'text/xml',content = document_dict['document'] )
# Convert if necessary styles_text = default_styles_text
opts = extra_context.get("options", None) if document_dict.has_key('stylesheet') and document_dict['stylesheet']:
if opts is not None: styles_text = document_dict['stylesheet']
format = opts.get('format', request.get('format', None)) if styles_text:
if format is not None: ooo_builder.addFileEntry(full_path = dir_name+'/styles.xml',
return self._asFormat(ooo, format, request) media_type = 'text/xml',content = styles_text )
else: # Generic case
# Do not send a RESPONSE if in batch_mode ooo_builder.addFileEntry(full_path=dir_name,
if request and not batch_mode: media_type=document_dict['doc_type'], content = document_dict['document'] )
request.RESPONSE.setHeader('Content-Type','%s;; charset=utf-8' % self.content_type)
request.RESPONSE.setHeader('Content-Length',len(ooo)) # Get request and batch_mode
request.RESPONSE.setHeader('Content-Disposition','inline;filename=%s' % batch_mode = extra_context.get('batch_mode', 0)
self.title_or_id())
# Debug mode
return ooo if request.get('debug',0):
return doc_xml
def om_icons(self):
"""Return a list of icon URLs to be displayed by an ObjectManager""" # Replace content.xml in master openoffice template
icons = ({'path': 'misc_/ERP5OOo/OOo.png', ooo_builder.replace('content.xml', doc_xml)
'alt': self.meta_type, 'title': self.meta_type},)
if not self._v_cooked: # Old templates correction
self._cook() try:
if self._v_errors: self.OLE_documents_zipstring
icons = icons + ({'path': 'misc_/PageTemplates/exclamation.gif', except AttributeError:
'alt': 'Error', self.OLE_documents_zipstring = None
'title': 'This template has an error'},)
return icons # If the file has embedded OLE documents, restore it
if self.OLE_documents_zipstring:
def _asPdf(self, ooo, REQUEST=None): additional_builder = OOoBuilder( self.OLE_documents_zipstring )
""" for name in additional_builder.getNameList():
Return OOo report as pdf ooo_builder.replace(name, additional_builder.extract(name) )
"""
return self._asFormat(ooo,'pdf',REQUEST) # Update the META informations
ooo_builder.updateManifest()
def _asFormat(self,ooo,format,REQUEST=None):
# now create a temp OOoDocument to convert data to pdf # Produce final result
from Products.ERP5Type.Document import newTempOOoDocument ooo = ooo_builder.render(self.title or self.id)
tmp_ooo = newTempOOoDocument(self, self.title_or_id())
tmp_ooo.edit(data = ooo, # Convert if necessary
fname = self.title_or_id(), opts = extra_context.get("options", None)
source_reference = self.title_or_id(), if opts is not None:
content_type = self.content_type,) format = opts.get('format', request.get('format', None))
tmp_ooo.oo_data = ooo if format is not None:
if format == 'pdf': return self._asFormat(ooo, format, request)
# slightly different implementation
# now convert it to pdf # Do not send a RESPONSE if in batch_mode
tgts=[x[1] for x in tmp_ooo.getTargetFormatItemList() if x[1].endswith('pdf')] if request and not batch_mode:
if len(tgts)>1: request.RESPONSE.setHeader('Content-Type','%s;; charset=utf-8' % self.content_type)
return tmp_ooo.returnMessage('multiple pdf formats found - this shouldnt happen') request.RESPONSE.setHeader('Content-Length',len(ooo))
if len(tgts)==0: request.RESPONSE.setHeader('Content-Disposition','inline;filename=%s' %
return tmp_ooo.returnMessage('no pdf format found') self.title_or_id())
fmt=tgts[0]
mime, data = tmp_ooo._makeFile(fmt) return ooo
if REQUEST is not None:
REQUEST.RESPONSE.setHeader('Content-type', 'application/pdf') def om_icons(self):
REQUEST.RESPONSE.setHeader('Content-disposition', 'attachment;; filename="%s.pdf"' % self.title_or_id()) """Return a list of icon URLs to be displayed by an ObjectManager"""
return data icons = ({'path': 'misc_/ERP5OOo/OOo.png',
# now for other formats 'alt': self.meta_type, 'title': self.meta_type},)
if not tmp_ooo.isAllowed(format): if not self._v_cooked:
errstr='%s format is not supported' % format self._cook()
return tmp_ooo.returnMessage(errstr) if self._v_errors:
try: icons = icons + ({'path': 'misc_/PageTemplates/exclamation.gif',
mime,data=tmp_ooo._makeFile(format) 'alt': 'Error',
except xmlrpclib.Fault,e: 'title': 'This template has an error'},)
return tmp_ooo.returnMessage('Problem: %s' % str(e)) return icons
if REQUEST is not None:
REQUEST.RESPONSE.setHeader('Content-type', mime) def _asPdf(self, ooo, REQUEST=None):
REQUEST.RESPONSE.setHeader('Content-disposition', 'attachment;; filename="%s.%s"' % (self.title_or_id(),format)) """
# FIXME the above lines should return zip format when html was requested Return OOo report as pdf
return data """
return self._asFormat(ooo,'pdf',REQUEST)
def _asFormat(self,ooo,format,REQUEST=None):
# now create a temp OOoDocument to convert data to pdf
from Products.ERP5Type.Document import newTempOOoDocument
tmp_ooo = newTempOOoDocument(self, self.title_or_id())
tmp_ooo.edit(data = ooo,
fname = self.title_or_id(),
source_reference = self.title_or_id(),
content_type = self.content_type,)
tmp_ooo.oo_data = ooo
if format == 'pdf':
# slightly different implementation
# now convert it to pdf
tgts=[x[1] for x in tmp_ooo.getTargetFormatItemList() if x[1].endswith('pdf')]
if len(tgts)>1:
return tmp_ooo.returnMessage('multiple pdf formats found - this shouldnt happen')
if len(tgts)==0:
return tmp_ooo.returnMessage('no pdf format found')
fmt=tgts[0]
mime, data = tmp_ooo._makeFile(fmt)
if REQUEST is not None:
REQUEST.RESPONSE.setHeader('Content-type', 'application/pdf')
REQUEST.RESPONSE.setHeader('Content-disposition', 'attachment;; filename="%s.pdf"' % self.title_or_id())
return data
# now for other formats
if not tmp_ooo.isAllowed(format):
errstr='%s format is not supported' % format
return tmp_ooo.returnMessage(errstr)
try:
mime,data=tmp_ooo._makeFile(format)
except xmlrpclib.Fault,e:
return tmp_ooo.returnMessage('Problem: %s' % str(e))
if REQUEST is not None:
REQUEST.RESPONSE.setHeader('Content-type', mime)
REQUEST.RESPONSE.setHeader('Content-disposition', 'attachment;; filename="%s.%s"' % (self.title_or_id(),format))
# FIXME the above lines should return zip format when html was requested
return data
InitializeClass(OOoTemplate) InitializeClass(OOoTemplate)
class FSOOoTemplate(FSPageTemplate, OOoTemplate): class FSOOoTemplate(FSPageTemplate, OOoTemplate):
meta_type = "ERP5 Filesystem OOo Template" meta_type = "ERP5 Filesystem OOo Template"
icon = "www/OOo.png" icon = "www/OOo.png"
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
return OOoTemplate.__call__(self, *args, **kwargs) return OOoTemplate.__call__(self, *args, **kwargs)
InitializeClass(FSOOoTemplate) InitializeClass(FSOOoTemplate)
registerFileExtension('ooot', FSOOoTemplate) registerFileExtension('ooot', FSOOoTemplate)
registerMetaType(OOoTemplate.meta_type, FSOOoTemplate) registerMetaType(OOoTemplate.meta_type, FSOOoTemplate)
\ No newline at end of file
# vim: syntax=python shiftwidth=2
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment