You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
9.3 KiB

  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com)
  5. #
  6. # Author : Guewen Baconnier (Camptocamp)
  7. #
  8. # WARNING: This program as such is intended to be used by professional
  9. # programmers who take the whole responsability of assessing all potential
  10. # consequences resulting from its eventual inadequacies and bugs
  11. # End users who are looking for a ready-to-use solution with commercial
  12. # garantees and support are strongly adviced to contract a Free Software
  13. # Service Company
  14. #
  15. # This program is Free Software; you can redistribute it and/or
  16. # modify it under the terms of the GNU General Public License
  17. # as published by the Free Software Foundation; either version 2
  18. # of the License, or (at your option) any later version.
  19. #
  20. # This program is distributed in the hope that it will be useful,
  21. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. # GNU General Public License for more details.
  24. #
  25. # You should have received a copy of the GNU General Public License
  26. # along with this program; if not, write to the Free Software
  27. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  28. #
  29. ##############################################################################
  30. import os
  31. import subprocess
  32. import tempfile
  33. import time
  34. import pooler
  35. import tools
  36. import openerp.addons
  37. from mako import exceptions
  38. from osv.osv import except_osv
  39. from tools.translate import _
  40. from openerp.addons.report_webkit import webkit_report
  41. from openerp.addons.report_webkit.webkit_report import mako_template
  42. from openerp.addons.report_webkit.report_helper import WebKitHelper
  43. # Class used only as a workaround to bug :
  44. # http://code.google.com/p/wkhtmltopdf/issues/detail?id=656
  45. # html headers and footers do not work on big files (hundreds of pages) so we replace them by
  46. # text headers and footers passed as arguments to wkhtmltopdf
  47. # this class has to be removed once the bug is fixed
  48. # in your report class, to print headers and footers as text, you have to add them in the localcontext with a key 'additional_args'
  49. # for instance :
  50. # header_report_name = _('PARTNER LEDGER')
  51. # footer_date_time = self.formatLang(str(datetime.today()), date_time=True)
  52. # self.localcontext.update({
  53. # 'additional_args': [
  54. # ('--header-font-name', 'Helvetica'),
  55. # ('--footer-font-name', 'Helvetica'),
  56. # ('--header-font-size', '10'),
  57. # ('--footer-font-size', '7'),
  58. # ('--header-left', header_report_name),
  59. # ('--footer-left', footer_date_time),
  60. # ('--footer-right', ' '.join((_('Page'), '[page]', _('of'), '[topage]'))),
  61. # ('--footer-line',),
  62. # ],
  63. # })
  64. class HeaderFooterTextWebKitParser(webkit_report.WebKitParser):
  65. def generate_pdf(self, comm_path, report_xml, header, footer, html_list, webkit_header=False):
  66. """Call webkit in order to generate pdf"""
  67. if not webkit_header:
  68. webkit_header = report_xml.webkit_header
  69. tmp_dir = tempfile.gettempdir()
  70. out_filename = tempfile.mktemp(suffix=".pdf", prefix="webkit.tmp.")
  71. files = []
  72. file_to_del = []
  73. if comm_path:
  74. command = [comm_path]
  75. else:
  76. command = ['wkhtmltopdf']
  77. command.append('--quiet')
  78. # default to UTF-8 encoding. Use <meta charset="latin-1"> to override.
  79. command.extend(['--encoding', 'utf-8'])
  80. if webkit_header.margin_top :
  81. command.extend(['--margin-top', str(webkit_header.margin_top).replace(',', '.')])
  82. if webkit_header.margin_bottom :
  83. command.extend(['--margin-bottom', str(webkit_header.margin_bottom).replace(',', '.')])
  84. if webkit_header.margin_left :
  85. command.extend(['--margin-left', str(webkit_header.margin_left).replace(',', '.')])
  86. if webkit_header.margin_right :
  87. command.extend(['--margin-right', str(webkit_header.margin_right).replace(',', '.')])
  88. if webkit_header.orientation :
  89. command.extend(['--orientation', str(webkit_header.orientation).replace(',', '.')])
  90. if webkit_header.format :
  91. command.extend(['--page-size', str(webkit_header.format).replace(',', '.')])
  92. if self.parser_instance.localcontext.get('additional_args', False):
  93. for arg in self.parser_instance.localcontext['additional_args']:
  94. command.extend(arg)
  95. count = 0
  96. for html in html_list :
  97. html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w')
  98. count += 1
  99. html_file.write(html)
  100. html_file.close()
  101. file_to_del.append(html_file.name)
  102. command.append(html_file.name)
  103. command.append(out_filename)
  104. try:
  105. status = subprocess.call(command, stderr=subprocess.PIPE) # ignore stderr
  106. if status :
  107. raise except_osv(
  108. _('Webkit raise an error' ),
  109. status
  110. )
  111. except Exception:
  112. for f_to_del in file_to_del :
  113. os.unlink(f_to_del)
  114. pdf = file(out_filename, 'rb').read()
  115. for f_to_del in file_to_del :
  116. os.unlink(f_to_del)
  117. os.unlink(out_filename)
  118. return pdf
  119. # override needed to keep the attachments' storing procedure
  120. def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None):
  121. """generate the PDF"""
  122. if context is None:
  123. context={}
  124. htmls = []
  125. if report_xml.report_type != 'webkit':
  126. return super(HeaderFooterTextWebKitParser,self).create_single_pdf(cursor, uid, ids, data, report_xml, context=context)
  127. self.parser_instance = self.parser(cursor,
  128. uid,
  129. self.name2,
  130. context=context)
  131. self.pool = pooler.get_pool(cursor.dbname)
  132. objs = self.getObjects(cursor, uid, ids, context)
  133. self.parser_instance.set_context(objs, data, ids, report_xml.report_type)
  134. template = False
  135. if report_xml.report_file :
  136. path =openerp.addons.get_module_resource(report_xml.report_file)
  137. if os.path.exists(path) :
  138. template = file(path).read()
  139. if not template and report_xml.report_webkit_data :
  140. template = report_xml.report_webkit_data
  141. if not template :
  142. raise except_osv(_('Error!'), _('Webkit Report template not found !'))
  143. header = report_xml.webkit_header.html
  144. footer = report_xml.webkit_header.footer_html
  145. if not header and report_xml.header:
  146. raise except_osv(
  147. _('No header defined for this Webkit report!'),
  148. _('Please set a header in company settings')
  149. )
  150. css = report_xml.webkit_header.css
  151. if not css :
  152. css = ''
  153. user = self.pool.get('res.users').browse(cursor, uid, uid)
  154. #default_filters=['unicode', 'entity'] can be used to set global filter
  155. body_mako_tpl = mako_template(template)
  156. helper = WebKitHelper(cursor, uid, report_xml.id, context)
  157. if report_xml.precise_mode:
  158. for obj in objs:
  159. self.parser_instance.localcontext['objects'] = [obj]
  160. try :
  161. html = body_mako_tpl.render(helper=helper,
  162. css=css,
  163. _=self.translate_call,
  164. **self.parser_instance.localcontext)
  165. htmls.append(html)
  166. except Exception, e:
  167. msg = exceptions.text_error_template().render()
  168. logger.error(msg)
  169. raise except_osv(_('Webkit render'), msg)
  170. else:
  171. try :
  172. html = body_mako_tpl.render(helper=helper,
  173. css=css,
  174. _=self.translate_call,
  175. **self.parser_instance.localcontext)
  176. htmls.append(html)
  177. except Exception, e:
  178. msg = exceptions.text_error_template().render()
  179. logger.error(msg)
  180. raise except_osv(_('Webkit render'), msg)
  181. # NO html footer and header because we write them as text with wkhtmltopdf
  182. head = foot = False
  183. if report_xml.webkit_debug :
  184. try :
  185. deb = body_mako_tpl.render(helper=helper,
  186. css=css,
  187. _debug=tools.ustr("\n".join(htmls)),
  188. _=self.translate_call,
  189. **self.parser_instance.localcontext)
  190. except Exception, e:
  191. msg = exceptions.text_error_template().render()
  192. logger.error(msg)
  193. raise except_osv(_('Webkit render'), msg)
  194. return (deb, 'html')
  195. bin = self.get_lib(cursor, uid)
  196. pdf = self.generate_pdf(bin, report_xml, head, foot, htmls)
  197. return (pdf, 'pdf')