Merge lp:~omar7r/openobject-addons/extra_trunk_pxgo_openoffice_reports into lp:openobject-addons/extra-trunk

Proposed by Omar (Pexego)
Status: Merged
Merged at revision: 5064
Proposed branch: lp:~omar7r/openobject-addons/extra_trunk_pxgo_openoffice_reports
Merge into: lp:openobject-addons/extra-trunk
Diff against target: 2779 lines (+2677/-0)
16 files modified
pxgo_openoffice_reports/__init__.py (+31/-0)
pxgo_openoffice_reports/__openerp__.py (+115/-0)
pxgo_openoffice_reports/demo/__init__.py (+1/-0)
pxgo_openoffice_reports/demo/partner_demo_bar_chart.yaml (+32/-0)
pxgo_openoffice_reports/demo/partner_demo_pie_chart.yaml (+23/-0)
pxgo_openoffice_reports/demo/partner_demo_report.xml (+50/-0)
pxgo_openoffice_reports/demo/report_parser.py (+42/-0)
pxgo_openoffice_reports/i18n/ca.po (+200/-0)
pxgo_openoffice_reports/i18n/es.po (+368/-0)
pxgo_openoffice_reports/i18n/it.po (+113/-0)
pxgo_openoffice_reports/i18n/pxgo_openoffice_reports.pot (+280/-0)
pxgo_openoffice_reports/oo_template.py (+599/-0)
pxgo_openoffice_reports/openoffice_report.py (+528/-0)
pxgo_openoffice_reports/report_xml.py (+189/-0)
pxgo_openoffice_reports/report_xml_view.xml (+103/-0)
pxgo_openoffice_reports/security/ir.model.access.csv (+3/-0)
To merge this branch: bzr merge lp:~omar7r/openobject-addons/extra_trunk_pxgo_openoffice_reports
Reviewer Review Type Date Requested Status
Borja López Soilán (NeoPolus) Approve
OpenERP Core Team Pending
Review via email: mp+39647@code.launchpad.net

Description of the change

Add pxgo_openoffice_reports module ported to 6.0

To post a comment you must log in.
Revision history for this message
Borja López Soilán (NeoPolus) (borjals) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'pxgo_openoffice_reports'
2=== added file 'pxgo_openoffice_reports/__init__.py'
3--- pxgo_openoffice_reports/__init__.py 1970-01-01 00:00:00 +0000
4+++ pxgo_openoffice_reports/__init__.py 2010-11-02 09:27:47 +0000
5@@ -0,0 +1,31 @@
6+# -*- coding: utf-8 -*-
7+# -*- encoding: utf-8 -*-
8+##############################################################################
9+#
10+# OpenOffice Reports
11+# Copyright (C) 2009 Pexego Sistemas Informáticos. All Rights Reserved
12+# $Id$
13+#
14+# This program is free software: you can redistribute it and/or modify
15+# it under the terms of the GNU General Public License as published by
16+# the Free Software Foundation, either version 3 of the License, or
17+# (at your option) any later version.
18+#
19+# This program is distributed in the hope that it will be useful,
20+# but WITHOUT ANY WARRANTY; without even the implied warranty of
21+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22+# GNU General Public License for more details.
23+#
24+# You should have received a copy of the GNU General Public License
25+# along with this program. If not, see <http://www.gnu.org/licenses/>.
26+#
27+##############################################################################
28+
29+"""
30+OpenOffice Reports - Reporting Engine based on Relatorio and OpenOffice.
31+"""
32+__author__ = "Borja López Soilán (Pexego)"
33+
34+import openoffice_report
35+import report_xml
36+#import demo
37\ No newline at end of file
38
39=== added file 'pxgo_openoffice_reports/__openerp__.py'
40--- pxgo_openoffice_reports/__openerp__.py 1970-01-01 00:00:00 +0000
41+++ pxgo_openoffice_reports/__openerp__.py 2010-11-02 09:27:47 +0000
42@@ -0,0 +1,115 @@
43+# -*- coding: utf-8 -*-
44+# -*- encoding: utf-8 -*-
45+##############################################################################
46+#
47+# OpenOffice Reports
48+# Copyright (C) 2009 Pexego Sistemas Informáticos. All Rights Reserved
49+# $Id$
50+#
51+# This program is free software: you can redistribute it and/or modify
52+# it under the terms of the GNU General Public License as published by
53+# the Free Software Foundation, either version 3 of the License, or
54+# (at your option) any later version.
55+#
56+# This program is distributed in the hope that it will be useful,
57+# but WITHOUT ANY WARRANTY; without even the implied warranty of
58+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59+# GNU General Public License for more details.
60+#
61+# You should have received a copy of the GNU General Public License
62+# along with this program. If not, see <http://www.gnu.org/licenses/>.
63+#
64+##############################################################################
65+#
66+# OpenOffice Reports - Reporting Engine based on Relatorio and OpenOffice.
67+#
68+# Autor: Borja López Soilán (Pexego)
69+#
70+{
71+ "name" : "Pexego OpenOffice Reports",
72+ "version" : "0.2",
73+ "author" : "Pexego",
74+ "website" : "http://www.pexego.es",
75+ "category" : "Enterprise Specific Modules",
76+ "description": """Pexego OpenOffice Reports - Reporting Engine based on Relatorio and OpenOffice.
77+
78+Reporting engine that uses OpenOffice and Relatorio to create reports from several kind of templates (like an OpenDocument Text, a Microsoft Excel spreadsheet, or even a PowerPoint!)
79+and export them on several formats (i.e.: it may create a Microsoft Excel spreadsheet from a OpenDocument spreadshet template).
80+
81+Based on Relatorio (see http://relatorio.openhex.org/), PyODConverter (http://www.artofsolving.com/opensource/pyodconverter) and the Jasper Reports addon from Koo (https://code.launchpad.net/openobject-client-kde).
82+
83+
84+*** FEATURES ***
85+
86+- The next template formats and output formats are supported:
87+ * Text (any text format supported by OpenOffice like odt, doc, rtf, txt):
88+ pdf, html, odt, doc (MS Word 97), rtf, txt
89+ * Web (hmtl):
90+ pdf, odt
91+ * Spreadsheet (ods, xls):
92+ pdf, html, ods, xls (MS Excel 97), csv
93+ * Presentation (odp, ppt):
94+ pdf, html, odp, ppt
95+ * Drawing (odg):
96+ pdf, swf
97+
98+- Subreports (inserting another file anywhere on the document) are supported for text formats,
99+ they are recursive (will be processed by the template system and may have their own subreports)
100+ and they can be loaded from a binary field.
101+
102+- Dynamic insertion of images is supported too, and they can be loaded from a file or a binary field.
103+
104+- Conditional statements (if) and repetitive structures (for) are supported. And they can be used in tables.
105+
106+
107+*** TEMPLATE LANGUAGE ***
108+
109+Templates are based on Relatorio and Genshi, you might find useful this introduction to Relatorio: http://relatorio.openhex.org/wiki/IndepthIntroduction
110+
111+Some additional features, mainly related to OpenERP, where added:
112+
113+ - Support for subreports (text documents only).
114+ * From OpenObject binary fields:
115+ ${ subreport(object.file_field, object.filename_field) }
116+ * From files on disk:
117+ ${ subreport(filepath='/tmp/something.odt') }
118+ * From buffers (open files, strings):
119+ ${ subreport(source=buffer, source_format='odt') }
120+
121+ - Translations using the OpenERP translation engine:
122+ ${ _("Object Name") }
123+
124+ - Access to attachments of an OpenObject:
125+ * Get the attachment names:
126+ ${ ', '.join([a.name for a in get_attachments(object)]) }
127+ * Use the first attachment as a subreport (only text documents):
128+ ${ subreport(get_attachments(object)[0].datas, get_attachments(object)[0].datas_fname) }
129+
130+ - Using images from fields:
131+ * On a frame name (see Relatorio documentation about including images),
132+ instead of "image: (file, mimetype)'",
133+ use "image: ${ field_to_image(object.field) }"
134+
135+
136+*** REQUIREMENTS ***
137+
138+- Relatorio (0.5.0 or better) for basic templating (odt->odt and ods->ods only),
139+- OpenOffice (2.4 or better) and PyUno for file conversions and subreports.
140+- Python Imaging Library (PIL) if you want to use images from binary fields.
141+- PyCha (3.0 or better) if you want to use charts.
142+- Genshi (0.5.1 or better) for using ${} instead of relatorio://
143+
144+ """,
145+ "depends" : [
146+ 'base',
147+ ],
148+ "init_xml" : [],
149+ "demo_xml" : [
150+ 'demo/partner_demo_report.xml',
151+ ],
152+ "update_xml" : [
153+ 'security/ir.model.access.csv',
154+ 'report_xml_view.xml',
155+ ],
156+ "installable": True
157+}
158
159=== added directory 'pxgo_openoffice_reports/custom_reports'
160=== added directory 'pxgo_openoffice_reports/demo'
161=== added file 'pxgo_openoffice_reports/demo/__init__.py'
162--- pxgo_openoffice_reports/demo/__init__.py 1970-01-01 00:00:00 +0000
163+++ pxgo_openoffice_reports/demo/__init__.py 2010-11-02 09:27:47 +0000
164@@ -0,0 +1,1 @@
165+import report_parser
166\ No newline at end of file
167
168=== added file 'pxgo_openoffice_reports/demo/partner_demo.ods'
169Binary files pxgo_openoffice_reports/demo/partner_demo.ods 1970-01-01 00:00:00 +0000 and pxgo_openoffice_reports/demo/partner_demo.ods 2010-11-02 09:27:47 +0000 differ
170=== added file 'pxgo_openoffice_reports/demo/partner_demo.odt'
171Binary files pxgo_openoffice_reports/demo/partner_demo.odt 1970-01-01 00:00:00 +0000 and pxgo_openoffice_reports/demo/partner_demo.odt 2010-11-02 09:27:47 +0000 differ
172=== added file 'pxgo_openoffice_reports/demo/partner_demo_bar_chart.yaml'
173--- pxgo_openoffice_reports/demo/partner_demo_bar_chart.yaml 1970-01-01 00:00:00 +0000
174+++ pxgo_openoffice_reports/demo/partner_demo_bar_chart.yaml 2010-11-02 09:27:47 +0000
175@@ -0,0 +1,32 @@
176+options:
177+ width: 800
178+ height: 800
179+ background:
180+ hide: true
181+ legend:
182+ hide: true
183+ padding:
184+ bottom: 50
185+ left: 120
186+ right: 30
187+ top: 10
188+ axis:
189+ x:
190+ label: 'Credit limit'
191+ rotate: 25
192+ ticks:
193+ {% for idx, partner in enumerate(objects) %}
194+ - v: $idx
195+ label: $partner.name
196+ {% end %}
197+ y:
198+ rotate: 25
199+chart:
200+ type: hbar
201+ output_type: png
202+ dataset:
203+ - - ${_('Credit limit')}
204+ -
205+ {% for idx, partner in enumerate(objects) %}
206+ - [$idx, $partner.credit_limit]
207+ {% end %}
208\ No newline at end of file
209
210=== added file 'pxgo_openoffice_reports/demo/partner_demo_not_auto.odt'
211Binary files pxgo_openoffice_reports/demo/partner_demo_not_auto.odt 1970-01-01 00:00:00 +0000 and pxgo_openoffice_reports/demo/partner_demo_not_auto.odt 2010-11-02 09:27:47 +0000 differ
212=== added file 'pxgo_openoffice_reports/demo/partner_demo_ods_output.xls'
213Binary files pxgo_openoffice_reports/demo/partner_demo_ods_output.xls 1970-01-01 00:00:00 +0000 and pxgo_openoffice_reports/demo/partner_demo_ods_output.xls 2010-11-02 09:27:47 +0000 differ
214=== added file 'pxgo_openoffice_reports/demo/partner_demo_odt_output.pdf'
215Binary files pxgo_openoffice_reports/demo/partner_demo_odt_output.pdf 1970-01-01 00:00:00 +0000 and pxgo_openoffice_reports/demo/partner_demo_odt_output.pdf 2010-11-02 09:27:47 +0000 differ
216=== added file 'pxgo_openoffice_reports/demo/partner_demo_pie_chart.yaml'
217--- pxgo_openoffice_reports/demo/partner_demo_pie_chart.yaml 1970-01-01 00:00:00 +0000
218+++ pxgo_openoffice_reports/demo/partner_demo_pie_chart.yaml 2010-11-02 09:27:47 +0000
219@@ -0,0 +1,23 @@
220+options:
221+ width: 400
222+ height: 400
223+ background:
224+ hide: true
225+ legend:
226+ hide: true
227+ padding:
228+ bottom: 10
229+ left: 70
230+ right: 10
231+ top: 10
232+ axis:
233+ labelFontSize: 16
234+chart:
235+ type: pie
236+ output_type: png
237+ dataset:
238+ {% for partner in objects %}
239+ - - ${partner.id}
240+ - - [0, $partner.credit_limit]
241+ {% end %}
242+
243
244=== added file 'pxgo_openoffice_reports/demo/partner_demo_report.xml'
245--- pxgo_openoffice_reports/demo/partner_demo_report.xml 1970-01-01 00:00:00 +0000
246+++ pxgo_openoffice_reports/demo/partner_demo_report.xml 2010-11-02 09:27:47 +0000
247@@ -0,0 +1,50 @@
248+<?xml version="1.0" encoding="utf-8"?>
249+<!--
250+ OpenOffice Reports - Sample partner report
251+ Autor: Borja López Soilán (Pexego)
252+-->
253+<openerp>
254+ <data>
255+
256+ <!-- Sample odt partner report -->
257+ <report id="report_pxgo_openoffice_reports_partner_demo"
258+ string="OpenOffice Reports Demo (ODT->PDF)"
259+ model="res.partner"
260+ name="pxgo_openoffice_reports.partner_demo"
261+ rml="pxgo_openoffice_reports/demo/partner_demo.odt"
262+ auto="True"
263+ header="False" />
264+ <record model="ir.actions.report.xml" id="report_pxgo_openoffice_reports_partner_demo">
265+ <field name="report_type">oo-pdf</field>
266+ </record>
267+
268+ <!-- Sample ods partner report -->
269+ <report id="report_pxgo_openoffice_reports_partner_demo_ods"
270+ string="OpenOffice Reports Demo (ODS->XLS)"
271+ model="res.partner"
272+ name="pxgo_openoffice_reports.partner_demo_ods"
273+ rml="pxgo_openoffice_reports/demo/partner_demo.ods"
274+ auto="True"
275+ header="False" />
276+ <record model="ir.actions.report.xml" id="report_pxgo_openoffice_reports_partner_demo_ods">
277+ <field name="report_type">oo-xls</field>
278+ </record>
279+
280+ <!-- Sample odt partner with parser when you can add more attributes to context-->
281+ <!-- It is commented because in demo data you cannot have python files, this report need report_parser.py file, if
282+ you want to test it discommented and write import demo in __init__.py-->
283+
284+ <!--<report id="report_pxgo_openoffice_reports_partner_demo_ods_not_auto"
285+ string="OpenOffice Reports Demo (ODT->PDF) not auto"
286+ model="res.partner"
287+ name="pxgo_openoffice_reports.partner_demo_ods_not_auto"
288+ rml="pxgo_openoffice_reports/demo/partner_demo_not_auto.odt"
289+ auto="False"
290+ header="False" />
291+ <record model="ir.actions.report.xml" id="report_pxgo_openoffice_reports_partner_demo_ods_not_auto">
292+ <field name="report_type">oo-pdf</field>
293+ </record>-->
294+
295+ </data>
296+</openerp>
297+
298\ No newline at end of file
299
300=== added file 'pxgo_openoffice_reports/demo/partner_demo_subreport.odt'
301Binary files pxgo_openoffice_reports/demo/partner_demo_subreport.odt 1970-01-01 00:00:00 +0000 and pxgo_openoffice_reports/demo/partner_demo_subreport.odt 2010-11-02 09:27:47 +0000 differ
302=== added file 'pxgo_openoffice_reports/demo/report_parser.py'
303--- pxgo_openoffice_reports/demo/report_parser.py 1970-01-01 00:00:00 +0000
304+++ pxgo_openoffice_reports/demo/report_parser.py 2010-11-02 09:27:47 +0000
305@@ -0,0 +1,42 @@
306+# -*- coding: utf-8 -*-
307+##############################################################################
308+#
309+# OpenERP, Open Source Management Solution
310+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
311+# $Id$
312+#
313+# This program is free software: you can redistribute it and/or modify
314+# it under the terms of the GNU General Public License as published by
315+# the Free Software Foundation, either version 3 of the License, or
316+# (at your option) any later version.
317+#
318+# This program is distributed in the hope that it will be useful,
319+# but WITHOUT ANY WARRANTY; without even the implied warranty of
320+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
321+# GNU General Public License for more details.
322+#
323+# You should have received a copy of the GNU General Public License
324+# along with this program. If not, see <http://www.gnu.org/licenses/>.
325+#
326+##############################################################################
327+
328+"""Add dummy function to context, it prints Hi! when you call it"""
329+
330+from addons.pxgo_openoffice_reports.openoffice_report import openoffice_report, OOReport
331+
332+class report_parser(OOReport):
333+ """Add dummy function to context, it prints Hi! when you call it"""
334+ def get_report_context(self):
335+ """Add dummy function to context, it prints Hi! when you call it"""
336+ res = super(report_parser, self).get_report_context()
337+ res.update({
338+ 'print_hi': self.print_hi,
339+ })
340+ return res
341+
342+ def print_hi(self):
343+ """Print Hi!"""
344+ res = "Hi !"
345+ return res
346+
347+openoffice_report('report.pxgo_openoffice_reports.partner_demo_ods_not_auto', 'res.partner', parser=report_parser)
348\ No newline at end of file
349
350=== added directory 'pxgo_openoffice_reports/i18n'
351=== added file 'pxgo_openoffice_reports/i18n/ca.po'
352--- pxgo_openoffice_reports/i18n/ca.po 1970-01-01 00:00:00 +0000
353+++ pxgo_openoffice_reports/i18n/ca.po 2010-11-02 09:27:47 +0000
354@@ -0,0 +1,200 @@
355+# Catalan translation for openobject-addons
356+# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
357+# This file is distributed under the same license as the openobject-addons package.
358+# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
359+#
360+msgid ""
361+msgstr ""
362+"Project-Id-Version: openobject-addons\n"
363+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
364+"POT-Creation-Date: 2009-11-27 17:29+0000\n"
365+"PO-Revision-Date: 2010-09-03 08:06+0000\n"
366+"Last-Translator: OpenERP Administrators <Unknown>\n"
367+"Language-Team: Catalan <ca@li.org>\n"
368+"MIME-Version: 1.0\n"
369+"Content-Type: text/plain; charset=UTF-8\n"
370+"Content-Transfer-Encoding: 8bit\n"
371+"X-Launchpad-Export-Date: 2010-09-29 05:32+0000\n"
372+"X-Generator: Launchpad (build Unknown)\n"
373+
374+#. module: pxgo_openoffice_reports
375+#: model:ir.module.module,description:pxgo_openoffice_reports.module_meta_information
376+msgid ""
377+"Pexego OpenOffice Reports - Reporting Engine based on Relatorio and "
378+"OpenOffice.\n"
379+"\n"
380+"Reporting engine that uses OpenOffice and Relatorio to create reports from "
381+"several kind of templates (like an OpenDocument Text, a Microsoft Excel "
382+"spreadsheet, or even a PowerPoint!) \n"
383+"and export them on several formats (i.e.: it may create a Microsoft Excel "
384+"spreadsheet from a OpenDocument spreadshet template).\n"
385+"\n"
386+"Based on Relatorio (see http://relatorio.openhex.org/), PyODConverter "
387+"(http://www.artofsolving.com/opensource/pyodconverter) and the Jasper "
388+"Reports addon from Koo (https://code.launchpad.net/openobject-client-kde).\n"
389+"\n"
390+"\n"
391+"*** FEATURES ***\n"
392+"\n"
393+"- The next template formats and output formats are supported:\n"
394+" * Text (any text format supported by OpenOffice like odt, doc, rtf, txt): "
395+"\n"
396+" pdf, html, odt, doc (MS Word 97), rtf, txt\n"
397+" * Web (hmtl): \n"
398+" pdf, odt\n"
399+" * Spreadsheet (ods, xls): \n"
400+" pdf, html, ods, xls (MS Excel 97), csv\n"
401+" * Presentation (odp, ppt): \n"
402+" pdf, html, odp, ppt\n"
403+" * Drawing (odg): \n"
404+" pdf, swf\n"
405+"\n"
406+"- Subreports (inserting another file anywhere on the document) are supported "
407+"for text formats,\n"
408+" they are recursive (will be processed by the template system and may have "
409+"their own subreports)\n"
410+" and they can be loaded from a binary field.\n"
411+" \n"
412+"- Dynamic insertion of images is supported too, and they can be loaded from "
413+"a file or a binary field.\n"
414+"\n"
415+"- Conditional statements (if) and repetitive structures (for) are supported. "
416+"And they can be used in tables.\n"
417+"\n"
418+"\n"
419+"*** TEMPLATE LANGUAGE ***\n"
420+"\n"
421+"Templates are based on Relatorio and Genshi, you might find useful this "
422+"introduction to Relatorio: "
423+"http://relatorio.openhex.org/wiki/IndepthIntroduction\n"
424+"\n"
425+"Some additional features, mainly related to OpenERP, where added:\n"
426+"\n"
427+" - Support for subreports (text documents only).\n"
428+" * From OpenObject binary fields:\n"
429+" ${ subreport(object.file_field, object.filename_field) }\n"
430+" * From files on disk:\n"
431+" ${ subreport(filepath='/tmp/something.odt') }\n"
432+" * From buffers (open files, strings):\n"
433+" ${ subreport(source=buffer, source_format='odt') }\n"
434+"\n"
435+" - Translations using the OpenERP translation engine:\n"
436+" ${ _(\"Object Name\") }\n"
437+"\n"
438+" - Access to attachments of an OpenObject:\n"
439+" * Get the attachment names:\n"
440+" ${ ', '.join([a.name for a in get_attachments(object)]) }\n"
441+" * Use the first attachment as a subreport (only text documents):\n"
442+" ${ subreport(get_attachments(object)[0].datas, "
443+"get_attachments(object)[0].datas_fname) }\n"
444+"\n"
445+" - Using images from fields:\n"
446+" * On a frame name (see Relatorio documentation about including "
447+"images),\n"
448+" instead of \"image: (file, mimetype)'\",\n"
449+" use \"image: field_to_image(object.field)\"\n"
450+"\n"
451+"\n"
452+"*** REQUIREMENTS ***\n"
453+"\n"
454+"- Relatorio (0.5.0 or better) for basic templating (odt->odt and ods->ods "
455+"only),\n"
456+"- OpenOffice (3.0 or better) and PyUno for file conversions and subreports.\n"
457+"- Python Imaging Library (PIL) if you want to use images from binary "
458+"fields.\n"
459+"- PyCha (3.0 or better) if you want to use charts.\n"
460+"\n"
461+" "
462+msgstr ""
463+"Informes OpenOffice Pexego - Motor d'informes basat en Relatorio i "
464+"OpenOffice.\n"
465+"\n"
466+"Motor d'informes que utilitza OpenOffice i Relatorio per a crear informes a "
467+"partir de varis tipus de plantilles (com un Text OpenDocument, un full de "
468+"càlcul de Microsoft Excel, o fins i tot un PowerPoint!) \n"
469+"i els exporta a varis formats (p.ex.: podeu crear un full de càlcul "
470+"Microsoft Excel a partir d'una plantilla de full de càlcul OpenDocument).\n"
471+"\n"
472+"Basat en Relatorio (veure http://relatorio.openhex.org/), PyODConverter "
473+"(http://www.artofsolving.com/opensource/pyodconverter) i el mòdul Jasper "
474+"Reports de Koo (https://code.launchpad.net/openobject-client-kde).\n"
475+"\n"
476+"\n"
477+"*** FUNCIONALITATS ***\n"
478+"\n"
479+"- Es suporten els següents formats de plantilla i de sortida:\n"
480+" * Text (qualsevol suportat per OpenOffice com odt, doc, rtf, txt): \n"
481+" pdf, html, odt, doc (MS Word 97), rtf, txt\n"
482+" * Web (hmtl): \n"
483+" pdf, odt\n"
484+" * Full de càlcul (ods, xls): \n"
485+" pdf, html, ods, xls (MS Excel 97), csv\n"
486+" * Presentació (odp, ppt): \n"
487+" pdf, html, odp, ppt\n"
488+" * Dibuix (odg): \n"
489+" pdf, swf\n"
490+"\n"
491+"- Suporta subinformes (inserir un altre fitxer en qualsevol lloc del "
492+"document) per als formats de text,\n"
493+" són recursius (seran processats pel sistema de plantilles i poden tenir "
494+"els seus propis subinformes)\n"
495+" i poden ser carregats des d'un camp binari.\n"
496+" \n"
497+"- També suporta inserció dinàmica d'imatges, que poden ser carregades des "
498+"d'un fitxer o un camp binari.\n"
499+"\n"
500+"- Suporta sentències condicionals (if) i estructures repetitives (for). I "
501+"poden ser utilitzats en taules.\n"
502+"\n"
503+"\n"
504+"*** IDIOMA DE LES PLANTILLES ***\n"
505+"\n"
506+"Les plantilles estan basades en Relatorio i Genshi, aquesta introducció a "
507+"Relatorio podria resultar-vos d'utilitat: "
508+"http://relatorio.openhex.org/wiki/IndepthIntroduction\n"
509+"\n"
510+"Es van afegir algunes funcionalitats addicionals, principalment relacionades "
511+"amb OpenERP:\n"
512+"\n"
513+" - Suport per a subinformes (només documents de text).\n"
514+" * Per a camps binaris d'OpenObject:\n"
515+" ${ subreport(object.file_field, object.filename_field) }\n"
516+" * Per a fitxers en disc:\n"
517+" ${ subreport(filepath='/tmp/something.odt') }\n"
518+" * Per a bufers (fitxers oberts, cadenes):\n"
519+" ${ subreport(source=buffer, source_format='odt') }\n"
520+"\n"
521+" - Traduccions utilitzen el motor de traduccions d'OpenERP:\n"
522+" ${ _(\"Object Name\") }\n"
523+"\n"
524+" - Accés als fitxers adjunts d'un OpenObject:\n"
525+" * Obtenir els noms dels adjunts:\n"
526+" ${ ', '.join([a.name for a in get_attachments(object)]) }\n"
527+" * Utilitzar el primer adjunt com un subinforme (només documents de "
528+"text):\n"
529+" ${ subreport(get_attachments(object)[0].datas, "
530+"get_attachments(object)[0].datas_fname) }\n"
531+"\n"
532+" - Utilitzant imatges des de camps:\n"
533+" * En el nom d'un marc (vegeu la documentació de Relatorio sobre "
534+"incloure imatges),\n"
535+" en lloc de \"image: (file, mimetype)'\",\n"
536+" utilitzeu \"image: field_to_image(object.field)\"\n"
537+"\n"
538+"\n"
539+"*** REQUISITS ***\n"
540+"\n"
541+"- Relatorio (0.5.0 o mejor) per a plantilles bàsiques (només odt->odt y ods-"
542+">ods),\n"
543+"- OpenOffice (3.0 o mejor) i PyUno per a conversió de fitxers i "
544+"subinformes.\n"
545+"- Python Imaging Library (PIL) si voleu utilitzar imatges des de camps "
546+"binaris.\n"
547+"- PyCha (3.0. or millor) if voleu utilitzar diagrames.\n"
548+"\n"
549+" "
550+
551+#. module: pxgo_openoffice_reports
552+#: model:ir.module.module,shortdesc:pxgo_openoffice_reports.module_meta_information
553+msgid "Pexego OpenOffice Reports"
554+msgstr "Informes OpenOffice Pexego"
555
556=== added file 'pxgo_openoffice_reports/i18n/es.po'
557--- pxgo_openoffice_reports/i18n/es.po 1970-01-01 00:00:00 +0000
558+++ pxgo_openoffice_reports/i18n/es.po 2010-11-02 09:27:47 +0000
559@@ -0,0 +1,368 @@
560+# Translation of OpenERP Server.
561+# This file contains the translation of the following modules:
562+# * pxgo_openoffice_reports
563+#
564+msgid ""
565+msgstr ""
566+"Project-Id-Version: OpenERP Server 6.0.0-rc1\n"
567+"Report-Msgid-Bugs-To: support@openerp.com\n"
568+"POT-Creation-Date: 2010-10-29 08:32:31+0000\n"
569+"PO-Revision-Date: 2010-10-29 10:40+0100\n"
570+"Last-Translator: omar <omar@pexego.es>\n"
571+"Language-Team: \n"
572+"MIME-Version: 1.0\n"
573+"Content-Type: text/plain; charset=UTF-8\n"
574+"Content-Transfer-Encoding: 8bit\n"
575+"Plural-Forms: \n"
576+
577+#. module: pxgo_openoffice_reports
578+#: field:ir.actions.report.xml,openoffice_report:0
579+msgid "Is OpenOffice Report?"
580+msgstr "Informe de OpenOffice"
581+
582+#: model:ir.module.module,description:pxgo_openoffice_reports.module_meta_information
583+msgid ""
584+"Pexego OpenOffice Reports - Reporting Engine based on Relatorio and "
585+"OpenOffice.\n"
586+"\n"
587+"Reporting engine that uses OpenOffice and Relatorio to create reports from "
588+"several kind of templates (like an OpenDocument Text, a Microsoft Excel "
589+"spreadsheet, or even a PowerPoint!) \n"
590+"and export them on several formats (i.e.: it may create a Microsoft Excel "
591+"spreadsheet from a OpenDocument spreadshet template).\n"
592+"\n"
593+"Based on Relatorio (see http://relatorio.openhex.org/), PyODConverter "
594+"(http://www.artofsolving.com/opensource/pyodconverter) and the Jasper "
595+"Reports addon from Koo (https://code.launchpad.net/openobject-client-kde).\n"
596+"\n"
597+"\n"
598+"*** FEATURES ***\n"
599+"\n"
600+"- The next template formats and output formats are supported:\n"
601+" * Text (any text format supported by OpenOffice like odt, doc, rtf, txt): "
602+"\n"
603+" pdf, html, odt, doc (MS Word 97), rtf, txt\n"
604+" * Web (hmtl): \n"
605+" pdf, odt\n"
606+" * Spreadsheet (ods, xls): \n"
607+" pdf, html, ods, xls (MS Excel 97), csv\n"
608+" * Presentation (odp, ppt): \n"
609+" pdf, html, odp, ppt\n"
610+" * Drawing (odg): \n"
611+" pdf, swf\n"
612+"\n"
613+"- Subreports (inserting another file anywhere on the document) are supported "
614+"for text formats,\n"
615+" they are recursive (will be processed by the template system and may have "
616+"their own subreports)\n"
617+" and they can be loaded from a binary field.\n"
618+" \n"
619+"- Dynamic insertion of images is supported too, and they can be loaded from "
620+"a file or a binary field.\n"
621+"\n"
622+"- Conditional statements (if) and repetitive structures (for) are supported. "
623+"And they can be used in tables.\n"
624+"\n"
625+"\n"
626+"*** TEMPLATE LANGUAGE ***\n"
627+"\n"
628+"Templates are based on Relatorio and Genshi, you might find useful this "
629+"introduction to Relatorio: "
630+"http://relatorio.openhex.org/wiki/IndepthIntroduction\n"
631+"\n"
632+"Some additional features, mainly related to OpenERP, where added:\n"
633+"\n"
634+" - Support for subreports (text documents only).\n"
635+" * From OpenObject binary fields:\n"
636+" ${ subreport(object.file_field, object.filename_field) }\n"
637+" * From files on disk:\n"
638+" ${ subreport(filepath='/tmp/something.odt') }\n"
639+" * From buffers (open files, strings):\n"
640+" ${ subreport(source=buffer, source_format='odt') }\n"
641+"\n"
642+" - Translations using the OpenERP translation engine:\n"
643+" ${ _(\"Object Name\") }\n"
644+"\n"
645+" - Access to attachments of an OpenObject:\n"
646+" * Get the attachment names:\n"
647+" ${ ', '.join([a.name for a in get_attachments(object)]) }\n"
648+" * Use the first attachment as a subreport (only text documents):\n"
649+" ${ subreport(get_attachments(object)[0].datas, "
650+"get_attachments(object)[0].datas_fname) }\n"
651+"\n"
652+" - Using images from fields:\n"
653+" * On a frame name (see Relatorio documentation about including "
654+"images),\n"
655+" instead of \"image: (file, mimetype)'\",\n"
656+" use \"image: field_to_image(object.field)\"\n"
657+"\n"
658+"\n"
659+"*** REQUIREMENTS ***\n"
660+"\n"
661+"- Relatorio (0.5.0 or better) for basic templating (odt->odt and ods->ods "
662+"only),\n"
663+"- OpenOffice (2.4 or better) and PyUno for file conversions and subreports.\n"
664+"- Python Imaging Library (PIL) if you want to use images from binary "
665+"fields.\n"
666+"- PyCha (3.0 or better) if you want to use charts.\n"
667+"- Genshi (0.5.1 or better) for using ${} instead of relatorio://\n"
668+"\n"
669+" "
670+msgstr ""
671+"Reportes OpenOffice Pexego - Motor de reportes basado en Relatorio y "
672+"OpenOffice.\n"
673+"\n"
674+"Motor de reportes que usa OpenOffice y Relatorio para crear reportes a "
675+"partir de varios tipos de plantillas (como un Texto OpenDocument, una hoja "
676+"de cálculo de Microsoft Excel, ¡o incluso un PowerPoint!) \n"
677+"y los exporta a varios formatos (p.ej.: puede crear una hoja de cálculo "
678+"Microsoft Excel a partir de una plantilla de hoja de cálculo OpenDocument).\n"
679+"\n"
680+"Basado en Relatorio (ver http://relatorio.openhex.org/), PyODConverter "
681+"(http://www.artofsolving.com/opensource/pyodconverter) y el módulo Jasper "
682+"Reports de Koo (https://code.launchpad.net/openobject-client-kde).\n"
683+"\n"
684+"\n"
685+"*** FUNCIONALIDADES ***\n"
686+"\n"
687+"- Se soportan los siguientes formatos de plantilla y de salida:\n"
688+" * Texto (cualquiera soportado por OpenOffice como odt, doc, rtf, txt): \n"
689+" pdf, html, odt, doc (MS Word 97), rtf, txt\n"
690+" * Web (hmtl): \n"
691+" pdf, odt\n"
692+" * Hoja de cálculo (ods, xls): \n"
693+" pdf, html, ods, xls (MS Excel 97), csv\n"
694+" * Presentación (odp, ppt): \n"
695+" pdf, html, odp, ppt\n"
696+" * Dibujo (odg): \n"
697+" pdf, swf\n"
698+"\n"
699+"- Soporta subreportes (insertar otro archivo en cualquier lugar del "
700+"documento) para los formatos de texto,\n"
701+" son recursivos (serán procesados por el sistema de plantillas y pueden "
702+"tener sus propios subreportes)\n"
703+" y pueden ser cargados desde un campo binario.\n"
704+" \n"
705+"- También soporta inserción dinámica de imágenes, que pueden ser cargadas "
706+"desde un archivo o un campo binario.\n"
707+"\n"
708+"- Soporta sentencias condicionales (if) y estructuras repetitivas (for). Y "
709+"pueden ser usados en tablas.\n"
710+"\n"
711+"\n"
712+"*** IDIOMA DE LAS PLANTILLAS ***\n"
713+"\n"
714+"Las plantillas están basadas en Relatorio y Genshi, esta introducción a "
715+"Relatorio podría resultarle de utilidad: "
716+"http://relatorio.openhex.org/wiki/IndepthIntroduction\n"
717+"\n"
718+"Se añadieron algunas funcionalidades adicionales, principalmente "
719+"relacionadas con OpenERP:\n"
720+"\n"
721+" - Soporte para subreportes (sólo documentos de texto).\n"
722+" * Para campos binarios de OpenObject:\n"
723+" ${ subreport(object.file_field, object.filename_field) }\n"
724+" * Para archivos en disco:\n"
725+" ${ subreport(filepath='/tmp/something.odt') }\n"
726+" * Para buferes (archivos abiertos, cadenas):\n"
727+" ${ subreport(source=buffer, source_format='odt') }\n"
728+"\n"
729+" - Traducciones usando el motor de traducciones de OpenERP:\n"
730+" ${ _(\"Object Name\") }\n"
731+"\n"
732+" - Acceso a los archivos adjuntos de un OpenObject:\n"
733+" * Obtener los nombres de los adjuntos:\n"
734+" ${ ', '.join([a.name for a in get_attachments(object)]) }\n"
735+" * Usar el primer adjunto como un subreporte (sólo documentos de "
736+"texto):\n"
737+" ${ subreport(get_attachments(object)[0].datas, "
738+"get_attachments(object)[0].datas_fname) }\n"
739+"\n"
740+" - Usando imágenes desde campos:\n"
741+" * En el nombre de un marco (vea la documentación de Relatorio acerca "
742+"de incluir imágenes),\n"
743+" en vez de \"image: (file, mimetype)'\",\n"
744+" use \"image: field_to_image(object.field)\"\n"
745+"\n"
746+"\n"
747+"*** REQUISITOS ***\n"
748+"\n"
749+"- Relatorio (0.5.0 o mejor) para plantillas básicas (sólo odt->odt y ods-"
750+">ods),\n"
751+"- OpenOffice (2.4 o mejor) y PyUno para conversión de archivos y "
752+"subreportes.\n"
753+"- Python Imaging Library (PIL) si quieres usar imágenes desde campos "
754+"binarios.\n"
755+"- PyCha (3.0. o mejor) if quieres usar diagramas.\n"
756+"- Genshi (0.5.1 o mejor) para usar expresiones ${} en lugar de relatorio://\n"
757+"\n"
758+" "
759+
760+#. module: pxgo_openoffice_reports
761+#: code:addons/pxgo_openoffice_reports/openoffice_report.py:0
762+#, python-format
763+msgid "Error loading the OpenOffice template: %s"
764+msgstr "Error cargando la plantilla de OpenOffice: %s"
765+
766+#. module: pxgo_openoffice_reports
767+#: model:ir.ui.menu,name:pxgo_openoffice_reports.openoffice_reports_menu
768+msgid "OpenOffice Reports"
769+msgstr "Informes OpenOffice"
770+
771+#. module: pxgo_openoffice_reports
772+#: constraint:ir.model:0
773+msgid "The Object name must start with x_ and not contain any special character !"
774+msgstr "¡El nombre del objeto debe empezar con x_ y no contener ningún carácter especial!"
775+
776+#. module: pxgo_openoffice_reports
777+#: constraint:ir.actions.act_window:0
778+msgid "Invalid model name in the action definition."
779+msgstr "Nombre de modelo no válido en la definición de acción."
780+
781+#. module: pxgo_openoffice_reports
782+#: code:addons/pxgo_openoffice_reports/openoffice_report.py:0
783+#, python-format
784+msgid "Error processing the OpenOffice template: %s"
785+msgstr "Error procesando la plantilla de OpenOffice: %s"
786+
787+#. module: pxgo_openoffice_reports
788+#: constraint:ir.ui.view:0
789+msgid "Invalid XML for View Architecture!"
790+msgstr "¡XML inválido para la definición de la vista!"
791+
792+#. module: pxgo_openoffice_reports
793+#: view:ir.actions.report.xml:0
794+msgid "openoffice Reports"
795+msgstr "Informes OpenOffice"
796+
797+#. module: pxgo_openoffice_reports
798+#: constraint:ir.ui.menu:0
799+msgid "Error ! You can not create recursive Menu."
800+msgstr "¡ Error ! No puede crear menús recursivos."
801+
802+#. module: pxgo_openoffice_reports
803+#: model:ir.actions.report.xml,name:pxgo_openoffice_reports.report_pxgo_openoffice_reports_partner_demo_ods
804+msgid "OpenOffice Reports Demo (ODS->XLS)"
805+msgstr "Informe OpenOffice demo (ODS->XLS)"
806+
807+#. module: pxgo_openoffice_reports
808+#: view:ir.actions.report.xml:0
809+#: field:ir.actions.report.xml,openoffice_file_ids:0
810+msgid "Files"
811+msgstr "Ficheros"
812+
813+#. module: pxgo_openoffice_reports
814+#: view:ir.actions.report.xml.file:0
815+msgid "Openoffice Reports File"
816+msgstr "Fichero informe Openoffice"
817+
818+#. module: pxgo_openoffice_reports
819+#: model:ir.actions.act_window,name:pxgo_openoffice_reports.ir_action_report_openoffice
820+#: view:ir.actions.report.xml:0
821+#: model:ir.ui.menu,name:pxgo_openoffice_reports.menu_ir_action_report_openoffice
822+msgid "Openoffice Reports"
823+msgstr "Informes Openoffice"
824+
825+#. module: pxgo_openoffice_reports
826+#: view:ir.actions.report.xml:0
827+msgid "Update from attachments"
828+msgstr "Actualizar desde adjuntos"
829+
830+#. module: pxgo_openoffice_reports
831+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
832+#, python-format
833+msgid "Error inserting file %s on the OpenOffice document: %s"
834+msgstr "Error insertando el fichero %s en el documento de OpenOffice: %s"
835+
836+#. module: pxgo_openoffice_reports
837+#: code:addons/pxgo_openoffice_reports/report_xml.py:0
838+#, python-format
839+msgid "There is more than one report marked as default"
840+msgstr "Hay más de un informe marcado como por defecto."
841+
842+#. module: pxgo_openoffice_reports
843+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
844+#, python-format
845+msgid "Error saving file %s with OpenOffice: %s"
846+msgstr "Error guardando el fichero %s con OpenOffice: %s"
847+
848+#. module: pxgo_openoffice_reports
849+#: view:ir.actions.report.xml:0
850+msgid "Groups"
851+msgstr "Grupos"
852+
853+#. module: pxgo_openoffice_reports
854+#: field:ir.actions.report.xml.file,report_id:0
855+msgid "Report"
856+msgstr "Informe"
857+
858+#. module: pxgo_openoffice_reports
859+#: code:addons/pxgo_openoffice_reports/__openerp__.py:0
860+#, python-format
861+msgid "Object Name"
862+msgstr "Nombre objeto"
863+
864+#. module: pxgo_openoffice_reports
865+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
866+#, python-format
867+msgid "Error loading file %s with OpenOffice: %s"
868+msgstr "Error cargando el fichero %s con OpenOffice: %s"
869+
870+#. module: pxgo_openoffice_reports
871+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
872+#, python-format
873+msgid "Couldn't connect to OpenOffice. Make sure you have an OpenOffice instance running and listening on the %s port. Details: %s"
874+msgstr "No se pudo conectar con OpenOffice. Asegúrese de tener una instancia de OpenOffice corriendo y escuchando el el puerto %s. Detalles: %s"
875+
876+#. module: pxgo_openoffice_reports
877+#: model:ir.model,name:pxgo_openoffice_reports.model_ir_actions_report_xml_file
878+msgid "ir.actions.report.xml.file"
879+msgstr "ir.actions.report.xml.file"
880+
881+#. module: pxgo_openoffice_reports
882+#: field:ir.actions.report.xml.file,default:0
883+msgid "Default"
884+msgstr "Por defecto"
885+
886+#. module: pxgo_openoffice_reports
887+#: code:addons/pxgo_openoffice_reports/report_xml.py:0
888+#, python-format
889+msgid "No report has been marked as default."
890+msgstr "Ningún informe ha sido marcado por defecto."
891+
892+#. module: pxgo_openoffice_reports
893+#: code:addons/pxgo_openoffice_reports/report_xml.py:0
894+#, python-format
895+msgid "Error"
896+msgstr "Error"
897+
898+#. module: pxgo_openoffice_reports
899+#: field:ir.actions.report.xml,openoffice_model_id:0
900+msgid "Model"
901+msgstr "Modelo"
902+
903+#. module: pxgo_openoffice_reports
904+#: model:ir.actions.report.xml,name:pxgo_openoffice_reports.report_pxgo_openoffice_reports_partner_demo
905+msgid "OpenOffice Reports Demo (ODT->PDF)"
906+msgstr "Informe OpenOffice demo (ODT->PDF)"
907+
908+#. module: pxgo_openoffice_reports
909+#: field:ir.actions.report.xml.file,filename:0
910+msgid "File Name"
911+msgstr "Nombre fichero"
912+
913+#. module: pxgo_openoffice_reports
914+#: model:ir.model,name:pxgo_openoffice_reports.model_ir_actions_report_xml
915+msgid "ir.actions.report.xml"
916+msgstr "ir.acciones.informe.xml"
917+
918+#. module: pxgo_openoffice_reports
919+#: field:ir.actions.report.xml.file,file:0
920+msgid "File"
921+msgstr "Fichero"
922+
923+#. module: pxgo_openoffice_reports
924+#: sql_constraint:ir.model.fields:0
925+msgid "Size of the field can never be less than 1 !"
926+msgstr "¡ El tamaño del campo no puede nunca ser menor que 1 !"
927+
928
929=== added file 'pxgo_openoffice_reports/i18n/it.po'
930--- pxgo_openoffice_reports/i18n/it.po 1970-01-01 00:00:00 +0000
931+++ pxgo_openoffice_reports/i18n/it.po 2010-11-02 09:27:47 +0000
932@@ -0,0 +1,113 @@
933+# Italian translation for openobject-addons
934+# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
935+# This file is distributed under the same license as the openobject-addons package.
936+# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
937+#
938+msgid ""
939+msgstr ""
940+"Project-Id-Version: openobject-addons\n"
941+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
942+"POT-Creation-Date: 2009-11-27 17:29+0000\n"
943+"PO-Revision-Date: 2010-08-18 12:15+0000\n"
944+"Last-Translator: OpenERP Administrators <Unknown>\n"
945+"Language-Team: Italian <it@li.org>\n"
946+"MIME-Version: 1.0\n"
947+"Content-Type: text/plain; charset=UTF-8\n"
948+"Content-Transfer-Encoding: 8bit\n"
949+"X-Launchpad-Export-Date: 2010-09-29 05:32+0000\n"
950+"X-Generator: Launchpad (build Unknown)\n"
951+
952+#. module: pxgo_openoffice_reports
953+#: model:ir.module.module,description:pxgo_openoffice_reports.module_meta_information
954+msgid ""
955+"Pexego OpenOffice Reports - Reporting Engine based on Relatorio and "
956+"OpenOffice.\n"
957+"\n"
958+"Reporting engine that uses OpenOffice and Relatorio to create reports from "
959+"several kind of templates (like an OpenDocument Text, a Microsoft Excel "
960+"spreadsheet, or even a PowerPoint!) \n"
961+"and export them on several formats (i.e.: it may create a Microsoft Excel "
962+"spreadsheet from a OpenDocument spreadshet template).\n"
963+"\n"
964+"Based on Relatorio (see http://relatorio.openhex.org/), PyODConverter "
965+"(http://www.artofsolving.com/opensource/pyodconverter) and the Jasper "
966+"Reports addon from Koo (https://code.launchpad.net/openobject-client-kde).\n"
967+"\n"
968+"\n"
969+"*** FEATURES ***\n"
970+"\n"
971+"- The next template formats and output formats are supported:\n"
972+" * Text (any text format supported by OpenOffice like odt, doc, rtf, txt): "
973+"\n"
974+" pdf, html, odt, doc (MS Word 97), rtf, txt\n"
975+" * Web (hmtl): \n"
976+" pdf, odt\n"
977+" * Spreadsheet (ods, xls): \n"
978+" pdf, html, ods, xls (MS Excel 97), csv\n"
979+" * Presentation (odp, ppt): \n"
980+" pdf, html, odp, ppt\n"
981+" * Drawing (odg): \n"
982+" pdf, swf\n"
983+"\n"
984+"- Subreports (inserting another file anywhere on the document) are supported "
985+"for text formats,\n"
986+" they are recursive (will be processed by the template system and may have "
987+"their own subreports)\n"
988+" and they can be loaded from a binary field.\n"
989+" \n"
990+"- Dynamic insertion of images is supported too, and they can be loaded from "
991+"a file or a binary field.\n"
992+"\n"
993+"- Conditional statements (if) and repetitive structures (for) are supported. "
994+"And they can be used in tables.\n"
995+"\n"
996+"\n"
997+"*** TEMPLATE LANGUAGE ***\n"
998+"\n"
999+"Templates are based on Relatorio and Genshi, you might find useful this "
1000+"introduction to Relatorio: "
1001+"http://relatorio.openhex.org/wiki/IndepthIntroduction\n"
1002+"\n"
1003+"Some additional features, mainly related to OpenERP, where added:\n"
1004+"\n"
1005+" - Support for subreports (text documents only).\n"
1006+" * From OpenObject binary fields:\n"
1007+" ${ subreport(object.file_field, object.filename_field) }\n"
1008+" * From files on disk:\n"
1009+" ${ subreport(filepath='/tmp/something.odt') }\n"
1010+" * From buffers (open files, strings):\n"
1011+" ${ subreport(source=buffer, source_format='odt') }\n"
1012+"\n"
1013+" - Translations using the OpenERP translation engine:\n"
1014+" ${ _(\"Object Name\") }\n"
1015+"\n"
1016+" - Access to attachments of an OpenObject:\n"
1017+" * Get the attachment names:\n"
1018+" ${ ', '.join([a.name for a in get_attachments(object)]) }\n"
1019+" * Use the first attachment as a subreport (only text documents):\n"
1020+" ${ subreport(get_attachments(object)[0].datas, "
1021+"get_attachments(object)[0].datas_fname) }\n"
1022+"\n"
1023+" - Using images from fields:\n"
1024+" * On a frame name (see Relatorio documentation about including "
1025+"images),\n"
1026+" instead of \"image: (file, mimetype)'\",\n"
1027+" use \"image: field_to_image(object.field)\"\n"
1028+"\n"
1029+"\n"
1030+"*** REQUIREMENTS ***\n"
1031+"\n"
1032+"- Relatorio (0.5.0 or better) for basic templating (odt->odt and ods->ods "
1033+"only),\n"
1034+"- OpenOffice (3.0 or better) and PyUno for file conversions and subreports.\n"
1035+"- Python Imaging Library (PIL) if you want to use images from binary "
1036+"fields.\n"
1037+"- PyCha (3.0 or better) if you want to use charts.\n"
1038+"\n"
1039+" "
1040+msgstr ""
1041+
1042+#. module: pxgo_openoffice_reports
1043+#: model:ir.module.module,shortdesc:pxgo_openoffice_reports.module_meta_information
1044+msgid "Pexego OpenOffice Reports"
1045+msgstr "Reports OpenOffice Pexego"
1046
1047=== added file 'pxgo_openoffice_reports/i18n/pxgo_openoffice_reports.pot'
1048--- pxgo_openoffice_reports/i18n/pxgo_openoffice_reports.pot 1970-01-01 00:00:00 +0000
1049+++ pxgo_openoffice_reports/i18n/pxgo_openoffice_reports.pot 2010-11-02 09:27:47 +0000
1050@@ -0,0 +1,280 @@
1051+# Translation of OpenERP Server.
1052+# This file contains the translation of the following modules:
1053+# * pxgo_openoffice_reports
1054+#
1055+msgid ""
1056+msgstr ""
1057+"Project-Id-Version: OpenERP Server 6.0.0-rc1\n"
1058+"Report-Msgid-Bugs-To: support@openerp.com\n"
1059+"POT-Creation-Date: 2010-10-29 08:32:31+0000\n"
1060+"PO-Revision-Date: 2010-10-29 10:40+0100\n"
1061+"Last-Translator: omar <omar@pexego.es>\n"
1062+"Language-Team: \n"
1063+"MIME-Version: 1.0\n"
1064+"Content-Type: text/plain; charset=UTF-8\n"
1065+"Content-Transfer-Encoding: 8bit\n"
1066+"Plural-Forms: \n"
1067+
1068+#. module: pxgo_openoffice_reports
1069+#: field:ir.actions.report.xml,openoffice_report:0
1070+msgid "Is OpenOffice Report?"
1071+msgstr ""
1072+
1073+#: model:ir.module.module,description:pxgo_openoffice_reports.module_meta_information
1074+msgid ""
1075+"Pexego OpenOffice Reports - Reporting Engine based on Relatorio and "
1076+"OpenOffice.\n"
1077+"\n"
1078+"Reporting engine that uses OpenOffice and Relatorio to create reports from "
1079+"several kind of templates (like an OpenDocument Text, a Microsoft Excel "
1080+"spreadsheet, or even a PowerPoint!) \n"
1081+"and export them on several formats (i.e.: it may create a Microsoft Excel "
1082+"spreadsheet from a OpenDocument spreadshet template).\n"
1083+"\n"
1084+"Based on Relatorio (see http://relatorio.openhex.org/), PyODConverter "
1085+"(http://www.artofsolving.com/opensource/pyodconverter) and the Jasper "
1086+"Reports addon from Koo (https://code.launchpad.net/openobject-client-kde).\n"
1087+"\n"
1088+"\n"
1089+"*** FEATURES ***\n"
1090+"\n"
1091+"- The next template formats and output formats are supported:\n"
1092+" * Text (any text format supported by OpenOffice like odt, doc, rtf, txt): "
1093+"\n"
1094+" pdf, html, odt, doc (MS Word 97), rtf, txt\n"
1095+" * Web (hmtl): \n"
1096+" pdf, odt\n"
1097+" * Spreadsheet (ods, xls): \n"
1098+" pdf, html, ods, xls (MS Excel 97), csv\n"
1099+" * Presentation (odp, ppt): \n"
1100+" pdf, html, odp, ppt\n"
1101+" * Drawing (odg): \n"
1102+" pdf, swf\n"
1103+"\n"
1104+"- Subreports (inserting another file anywhere on the document) are supported "
1105+"for text formats,\n"
1106+" they are recursive (will be processed by the template system and may have "
1107+"their own subreports)\n"
1108+" and they can be loaded from a binary field.\n"
1109+" \n"
1110+"- Dynamic insertion of images is supported too, and they can be loaded from "
1111+"a file or a binary field.\n"
1112+"\n"
1113+"- Conditional statements (if) and repetitive structures (for) are supported. "
1114+"And they can be used in tables.\n"
1115+"\n"
1116+"\n"
1117+"*** TEMPLATE LANGUAGE ***\n"
1118+"\n"
1119+"Templates are based on Relatorio and Genshi, you might find useful this "
1120+"introduction to Relatorio: "
1121+"http://relatorio.openhex.org/wiki/IndepthIntroduction\n"
1122+"\n"
1123+"Some additional features, mainly related to OpenERP, where added:\n"
1124+"\n"
1125+" - Support for subreports (text documents only).\n"
1126+" * From OpenObject binary fields:\n"
1127+" ${ subreport(object.file_field, object.filename_field) }\n"
1128+" * From files on disk:\n"
1129+" ${ subreport(filepath='/tmp/something.odt') }\n"
1130+" * From buffers (open files, strings):\n"
1131+" ${ subreport(source=buffer, source_format='odt') }\n"
1132+"\n"
1133+" - Translations using the OpenERP translation engine:\n"
1134+" ${ _(\"Object Name\") }\n"
1135+"\n"
1136+" - Access to attachments of an OpenObject:\n"
1137+" * Get the attachment names:\n"
1138+" ${ ', '.join([a.name for a in get_attachments(object)]) }\n"
1139+" * Use the first attachment as a subreport (only text documents):\n"
1140+" ${ subreport(get_attachments(object)[0].datas, "
1141+"get_attachments(object)[0].datas_fname) }\n"
1142+"\n"
1143+" - Using images from fields:\n"
1144+" * On a frame name (see Relatorio documentation about including "
1145+"images),\n"
1146+" instead of \"image: (file, mimetype)'\",\n"
1147+" use \"image: field_to_image(object.field)\"\n"
1148+"\n"
1149+"\n"
1150+"*** REQUIREMENTS ***\n"
1151+"\n"
1152+"- Relatorio (0.5.0 or better) for basic templating (odt->odt and ods->ods "
1153+"only),\n"
1154+"- OpenOffice (2.4 or better) and PyUno for file conversions and subreports.\n"
1155+"- Python Imaging Library (PIL) if you want to use images from binary "
1156+"fields.\n"
1157+"- PyCha (3.0 or better) if you want to use charts.\n"
1158+"- Genshi (0.5.1 or better) for using ${} instead of relatorio://\n"
1159+"\n"
1160+" "
1161+msgstr ""
1162+
1163+#. module: pxgo_openoffice_reports
1164+#: code:addons/pxgo_openoffice_reports/openoffice_report.py:0
1165+#, python-format
1166+msgid "Error loading the OpenOffice template: %s"
1167+msgstr ""
1168+
1169+#. module: pxgo_openoffice_reports
1170+#: model:ir.ui.menu,name:pxgo_openoffice_reports.openoffice_reports_menu
1171+msgid "OpenOffice Reports"
1172+msgstr ""
1173+
1174+#. module: pxgo_openoffice_reports
1175+#: constraint:ir.model:0
1176+msgid "The Object name must start with x_ and not contain any special character !"
1177+msgstr ""
1178+
1179+#. module: pxgo_openoffice_reports
1180+#: constraint:ir.actions.act_window:0
1181+msgid "Invalid model name in the action definition."
1182+msgstr ""
1183+
1184+#. module: pxgo_openoffice_reports
1185+#: code:addons/pxgo_openoffice_reports/openoffice_report.py:0
1186+#, python-format
1187+msgid "Error processing the OpenOffice template: %s"
1188+msgstr ""
1189+
1190+#. module: pxgo_openoffice_reports
1191+#: constraint:ir.ui.view:0
1192+msgid "Invalid XML for View Architecture!"
1193+msgstr ""
1194+
1195+#. module: pxgo_openoffice_reports
1196+#: view:ir.actions.report.xml:0
1197+msgid "openoffice Reports"
1198+msgstr ""
1199+
1200+#. module: pxgo_openoffice_reports
1201+#: constraint:ir.ui.menu:0
1202+msgid "Error ! You can not create recursive Menu."
1203+msgstr ""
1204+
1205+#. module: pxgo_openoffice_reports
1206+#: model:ir.actions.report.xml,name:pxgo_openoffice_reports.report_pxgo_openoffice_reports_partner_demo_ods
1207+msgid "OpenOffice Reports Demo (ODS->XLS)"
1208+msgstr ""
1209+
1210+#. module: pxgo_openoffice_reports
1211+#: view:ir.actions.report.xml:0
1212+#: field:ir.actions.report.xml,openoffice_file_ids:0
1213+msgid "Files"
1214+msgstr ""
1215+
1216+#. module: pxgo_openoffice_reports
1217+#: view:ir.actions.report.xml.file:0
1218+msgid "Openoffice Reports File"
1219+msgstr ""
1220+
1221+#. module: pxgo_openoffice_reports
1222+#: model:ir.actions.act_window,name:pxgo_openoffice_reports.ir_action_report_openoffice
1223+#: view:ir.actions.report.xml:0
1224+#: model:ir.ui.menu,name:pxgo_openoffice_reports.menu_ir_action_report_openoffice
1225+msgid "Openoffice Reports"
1226+msgstr ""
1227+
1228+#. module: pxgo_openoffice_reports
1229+#: view:ir.actions.report.xml:0
1230+msgid "Update from attachments"
1231+msgstr ""
1232+
1233+#. module: pxgo_openoffice_reports
1234+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
1235+#, python-format
1236+msgid "Error inserting file %s on the OpenOffice document: %s"
1237+msgstr ""
1238+
1239+#. module: pxgo_openoffice_reports
1240+#: code:addons/pxgo_openoffice_reports/report_xml.py:0
1241+#, python-format
1242+msgid "There is more than one report marked as default"
1243+msgstr ""
1244+
1245+#. module: pxgo_openoffice_reports
1246+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
1247+#, python-format
1248+msgid "Error saving file %s with OpenOffice: %s"
1249+msgstr ""
1250+
1251+#. module: pxgo_openoffice_reports
1252+#: view:ir.actions.report.xml:0
1253+msgid "Groups"
1254+msgstr ""
1255+
1256+#. module: pxgo_openoffice_reports
1257+#: field:ir.actions.report.xml.file,report_id:0
1258+msgid "Report"
1259+msgstr ""
1260+
1261+#. module: pxgo_openoffice_reports
1262+#: code:addons/pxgo_openoffice_reports/__openerp__.py:0
1263+#, python-format
1264+msgid "Object Name"
1265+msgstr ""
1266+
1267+#. module: pxgo_openoffice_reports
1268+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
1269+#, python-format
1270+msgid "Error loading file %s with OpenOffice: %s"
1271+msgstr ""
1272+
1273+#. module: pxgo_openoffice_reports
1274+#: code:addons/pxgo_openoffice_reports/oo_template.py:0
1275+#, python-format
1276+msgid "Couldn't connect to OpenOffice. Make sure you have an OpenOffice instance running and listening on the %s port. Details: %s"
1277+msgstr ""
1278+
1279+#. module: pxgo_openoffice_reports
1280+#: model:ir.model,name:pxgo_openoffice_reports.model_ir_actions_report_xml_file
1281+msgid "ir.actions.report.xml.file"
1282+msgstr ""
1283+
1284+#. module: pxgo_openoffice_reports
1285+#: field:ir.actions.report.xml.file,default:0
1286+msgid "Default"
1287+msgstr ""
1288+
1289+#. module: pxgo_openoffice_reports
1290+#: code:addons/pxgo_openoffice_reports/report_xml.py:0
1291+#, python-format
1292+msgid "No report has been marked as default."
1293+msgstr ""
1294+
1295+#. module: pxgo_openoffice_reports
1296+#: code:addons/pxgo_openoffice_reports/report_xml.py:0
1297+#, python-format
1298+msgid "Error"
1299+msgstr ""
1300+
1301+#. module: pxgo_openoffice_reports
1302+#: field:ir.actions.report.xml,openoffice_model_id:0
1303+msgid "Model"
1304+msgstr ""
1305+
1306+#. module: pxgo_openoffice_reports
1307+#: model:ir.actions.report.xml,name:pxgo_openoffice_reports.report_pxgo_openoffice_reports_partner_demo
1308+msgid "OpenOffice Reports Demo (ODT->PDF)"
1309+msgstr ""
1310+
1311+#. module: pxgo_openoffice_reports
1312+#: field:ir.actions.report.xml.file,filename:0
1313+msgid "File Name"
1314+msgstr ""
1315+
1316+#. module: pxgo_openoffice_reports
1317+#: model:ir.model,name:pxgo_openoffice_reports.model_ir_actions_report_xml
1318+msgid "ir.actions.report.xml"
1319+msgstr ""
1320+
1321+#. module: pxgo_openoffice_reports
1322+#: field:ir.actions.report.xml.file,file:0
1323+msgid "File"
1324+msgstr ""
1325+
1326+#. module: pxgo_openoffice_reports
1327+#: sql_constraint:ir.model.fields:0
1328+msgid "Size of the field can never be less than 1 !"
1329+msgstr ""
1330+
1331
1332=== added file 'pxgo_openoffice_reports/oo_template.py'
1333--- pxgo_openoffice_reports/oo_template.py 1970-01-01 00:00:00 +0000
1334+++ pxgo_openoffice_reports/oo_template.py 2010-11-02 09:27:47 +0000
1335@@ -0,0 +1,599 @@
1336+# -*- coding: utf-8 -*-
1337+# -*- encoding: utf-8 -*-
1338+##############################################################################
1339+#
1340+# OpenOffice Reports
1341+# Copyright (C) 2009 Pexego Sistemas Informáticos. All Rights Reserved
1342+# Based on Relatorio (see http://relatorio.openhex.org/)
1343+# and PyODConverter (http://www.artofsolving.com/opensource/pyodconverter)
1344+# $Id$
1345+#
1346+# This program is free software: you can redistribute it and/or modify
1347+# it under the terms of the GNU General Public License as published by
1348+# the Free Software Foundation, either version 3 of the License, or
1349+# (at your option) any later version.
1350+#
1351+# This program is distributed in the hope that it will be useful,
1352+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1353+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1354+# GNU General Public License for more details.
1355+#
1356+# You should have received a copy of the GNU General Public License
1357+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1358+#
1359+##############################################################################
1360+
1361+"""
1362+OpenOffice/Relatorio template engine.
1363+"""
1364+__author__ = "Borja López Soilán (Pexego)"
1365+
1366+from tools.translate import _
1367+import os
1368+import tempfile
1369+import inspect
1370+import base64
1371+import subprocess
1372+import time
1373+import genshi
1374+from os.path import abspath, splitext
1375+from relatorio.templates.opendocument import Template
1376+
1377+
1378+class OOTemplateException(Exception):
1379+ """
1380+ OpenOffice template exception
1381+ """
1382+ def __init__(self, message):
1383+ # pylint: disable-msg=W0231
1384+ self.message = message
1385+ def __str__(self):
1386+ return self.message
1387+
1388+
1389+class OOTemplate(Template):
1390+ """
1391+ OpenOffice/Relatorio template.
1392+ Extends the standard relatorio template to let the user include subreports
1393+ with the "${ subreport(file, context) }" statement,
1394+ and allow file conversions (pdf output and such).
1395+
1396+ Note: It needs an OpenOffice instance running and listening for the
1397+ advanced features.
1398+ """
1399+
1400+ def log(self, message):
1401+ """
1402+ Helper method used print debug messages
1403+ """
1404+ if self.logger:
1405+ self.logger(message)
1406+ else:
1407+ print "OOTemplate: %s" % message
1408+
1409+
1410+ def __init__(self, source=None, filepath=None, filename=None, loader=None,
1411+ encoding=None, lookup='strict', allow_exec=True,
1412+ source_format=None, output_format=None,
1413+ openoffice_port=8100, autostart_openoffice=True,
1414+ logger=None):
1415+ """
1416+ Init the oo_subreports list, OpenOffice options and formats,
1417+ and then delegate on the parent constructor.
1418+ """
1419+ self.logger = logger
1420+
1421+ self.temp_file_names = [] # List of files to delete on the destructor (__del__)
1422+ assert filepath or filename or source_format
1423+
1424+ if source:
1425+ #
1426+ # Relatorio reports don't support using source instead of filepath/filename.
1427+ # Passing the file contents using source seems useful, but
1428+ # we will have to write it somewhere for Relatorio to work.
1429+ # So we will create a temp file (that will be removed when
1430+ # oo_render ends, and dump source to that file.
1431+ #
1432+ assert isinstance(source, (file, str, unicode))
1433+ self.log("Template is a file-like object or string, writing it to a temp file.")
1434+ dummy_fd, temp_file_name = tempfile.mkstemp(suffix=".%s" % source_format, prefix='openerp_oot_t_')
1435+ temp_file = open(temp_file_name, 'wb')
1436+ try:
1437+ if isinstance(source, file):
1438+ temp_file.write(source.read())
1439+ elif isinstance(source, (str, unicode)):
1440+ temp_file.write(source)
1441+ finally:
1442+ temp_file.close()
1443+ self.temp_file_names.append(temp_file_name)
1444+ filepath = temp_file_name
1445+
1446+ filepath = filepath or filename
1447+ filename = None
1448+ assert filepath
1449+
1450+ if not os.path.exists(filepath):
1451+ search_paths = ['./bin/addons/%s' % filepath, './addons/%s' % filepath]
1452+ for path in search_paths:
1453+ if os.path.exists(path):
1454+ filepath = path
1455+ break
1456+
1457+ if not source_format:
1458+ # Get the source_format from the file name:
1459+ source_format = splitext(filepath or filename)[1][1:]
1460+
1461+ assert source_format and output_format
1462+ source_format = source_format.lower()
1463+ output_format = output_format.lower()
1464+
1465+ if source_format in ('doc', 'rtf', 'txt', 'xls'):
1466+ # It's not an OpenDocument file,
1467+ # (it may be a Microsoft Word document [doc] for example),
1468+ # convert it using OpenOffice.
1469+ format_mapping = { 'doc': 'odt', 'rtf': 'odt', 'txt': 'odt', 'xls': 'ods'}
1470+ self.log("Template file is not an OpenDocument, converting from %s to %s." % (source_format, format_mapping[source_format]))
1471+ dummy_fd, temp_file_name = tempfile.mkstemp(suffix=".%s" % format_mapping[source_format], prefix='openerp_oot_t_')
1472+ oohelper = OOHelper(openoffice_port, autostart_openoffice, logger=self.logger)
1473+ document = oohelper.open_document(filepath)
1474+ oohelper.save_document(document, temp_file_name, close_document=True)
1475+ self.temp_file_names.append(temp_file_name)
1476+ source_format = format_mapping[source_format]
1477+ filepath = temp_file_name
1478+
1479+ self.source_format = source_format
1480+ self.output_format = output_format
1481+ self.openoffice_port = openoffice_port
1482+ self.autostart_openoffice = autostart_openoffice
1483+ self.oo_subreports = []
1484+
1485+ super(OOTemplate, self).__init__(source, filepath, filename, loader,
1486+ encoding, lookup, allow_exec)
1487+
1488+
1489+ def __del__(self):
1490+ """
1491+ Destructor of the template: Will delete any temp file created on the
1492+ constructor.
1493+ """
1494+ if self.temp_file_names:
1495+ for file_name in self.temp_file_names:
1496+ os.unlink(file_name)
1497+
1498+
1499+ def generate(self, *args, **kwargs):
1500+ """
1501+ Apply the template to the given context data.
1502+ Overwrites the generate method to add support for subreports.
1503+ Delegates on the standard generate method for everything else.
1504+ """
1505+ def _subreport(field=None, filename=None, source=None, filepath=None, source_format=None, encoding=None, context=None):
1506+ """
1507+ Method that can be referenced from the template to include subreports.
1508+ When called it will process the file as a template,
1509+ write the generated data to a temp file,
1510+ and return a reference (filename) to this output file for later usage.
1511+ The OOTemplate will will use this data, after the main template
1512+ is generated, to do an insertion pass using UNO.
1513+ """
1514+ # Field is a binary field with a base64 encoded file that we will
1515+ # use as source if it is specified
1516+ source = field and base64.decodestring(field) or source
1517+
1518+ #
1519+ # Get the current report context so the subreport can see
1520+ # the variables defined on the report.
1521+ #
1522+ if not context:
1523+ context = {}
1524+ try:
1525+ frame = inspect.stack()[1][0]
1526+ locals_context = frame.f_locals.copy()
1527+ data_context = locals_context.get('__data__') or context
1528+ if data_context and isinstance(data_context, genshi.template.base.Context):
1529+ for c in data_context.frames:
1530+ context.update(c)
1531+ else:
1532+ context = data_context
1533+ except:
1534+ self.log("Warning: Failed to get the context for the subreport from the stack frame!")
1535+
1536+
1537+ # Get the source_format from the file name:
1538+ if not source_format and (filepath or filename):
1539+ source_format = splitext(filepath or filename)[1][1:]
1540+ source_format = source_format or self.source_format
1541+ assert source_format
1542+
1543+ #
1544+ # Process the subreport file like a normal template
1545+ # (we are recursive!)
1546+ #
1547+ self.log("Generating subreport (%s)..." % source_format)
1548+ subreport_template = OOTemplate(source=source,
1549+ filepath=filepath,
1550+ filename=filename,
1551+ encoding=encoding,
1552+ source_format=source_format,
1553+ output_format=self.source_format,
1554+ openoffice_port=self.openoffice_port,
1555+ autostart_openoffice=self.autostart_openoffice,
1556+ logger=self.log)
1557+ data = subreport_template.oo_render(context)
1558+
1559+ #
1560+ # Save the subreport data to a temp file
1561+ #
1562+ dummy_fd, temp_file_name = tempfile.mkstemp(suffix=".%s" % source_format, prefix='openerp_oot_s_')
1563+ temp_file = open(temp_file_name, 'wb')
1564+ try:
1565+ temp_file.write(data)
1566+ finally:
1567+ temp_file.close()
1568+
1569+ #
1570+ # Save a reference to this file for later usage
1571+ #
1572+ self.oo_subreports.append(temp_file_name)
1573+ self.log("...subreport generated as %s." % temp_file_name)
1574+
1575+ # Return a placeholder that will be replaced later,
1576+ # on the insertion step, with the file contents:
1577+ return "${insert_doc('%s')}" % temp_file_name
1578+
1579+ # Add the include function to the report context
1580+ kwargs['subreport'] = _subreport
1581+
1582+ # Generate the template
1583+ res = super(OOTemplate, self).generate(*args, **kwargs)
1584+
1585+ return res
1586+
1587+
1588+
1589+ def oo_render(self, context=None):
1590+ """
1591+ Wrapper, around the render method of the original template,
1592+ that adds support for subreports and format conversion.
1593+ The wrapper is required as these operations need to be performed,
1594+ using OpenOffice, after the document generation by the template.
1595+ """
1596+ if context is None: context = {}
1597+ self.log("Generating report: step 1...")
1598+
1599+ # Generate the stream from the template (Relatorio)
1600+ data = self.generate(**context).render().getvalue()
1601+
1602+ self.log("...step 1 done.")
1603+
1604+ #
1605+ # Next steps need OpenOffice to perform some tasks
1606+ # like file insertion or format conversions.
1607+ # Using OpenOffice brings some overhead, so we will try to avoid
1608+ # connecting to it unless it is necesary.
1609+ #
1610+ if len(self.oo_subreports)>0 or (self.output_format != self.source_format):
1611+ self.log("Step 2....")
1612+
1613+ # Connect to OpenOffice
1614+ oohelper = OOHelper(self.openoffice_port, self.autostart_openoffice, logger=self.log)
1615+
1616+ #
1617+ # Create a temporary (input for OpenOffice) file
1618+ #
1619+ dummy_fd, temp_file_name = tempfile.mkstemp(suffix=".%s" % self.source_format, prefix='openerp_oot_i_')
1620+ temp_file = open(temp_file_name, 'wb')
1621+ try:
1622+ #
1623+ # Write the data to the file
1624+ #
1625+ try:
1626+ temp_file.write(data)
1627+ finally:
1628+ temp_file.close()
1629+
1630+ # Reopen the file with OpenOffice
1631+ document = oohelper.open_document(temp_file_name)
1632+
1633+ #
1634+ # Insert subreport files if needed
1635+ #
1636+ if len(self.oo_subreports)>0:
1637+ self.log("Inserting subreport files")
1638+ for subreport in self.oo_subreports:
1639+ placeholder_text = "${insert_doc('%s')}" % subreport
1640+ oohelper.replace_text_with_file_contents(document, placeholder_text, subreport)
1641+ # Remove the subreport temp file
1642+ os.unlink(subreport)
1643+
1644+ #
1645+ # Save the file (does the format conversion) on a temp file
1646+ #
1647+ dummy_fd, output_file_name = tempfile.mkstemp(suffix=".%s" % self.output_format, prefix='openerp_oot_o_')
1648+ try:
1649+ # Save the document
1650+ oohelper.save_document(document, output_file_name, close_document=True)
1651+
1652+ #
1653+ # Read back the data
1654+ #
1655+ output_file = open(output_file_name, 'rb')
1656+ try:
1657+ data = output_file.read()
1658+ finally:
1659+ output_file.close()
1660+ finally:
1661+ # Remove the temp file
1662+ os.unlink(output_file_name)
1663+ finally:
1664+ # Remove the temp file
1665+ os.unlink(temp_file_name)
1666+
1667+ self.log("...step 2 done.")
1668+
1669+
1670+ # TODO: As a long term feature it would be nice to be able to tell OpenOffice to refresh/recalculate the Table Of Contents (if there is any)
1671+
1672+
1673+ # Return the data (byte string)
1674+ return data
1675+
1676+
1677+
1678+
1679+class OOHelperException(Exception):
1680+ """
1681+ OpenOffice template exception
1682+ """
1683+ def __init__(self, message):
1684+ # pylint: disable-msg=W0231
1685+ self.message = message
1686+ def __str__(self):
1687+ return self.message
1688+
1689+
1690+
1691+class OOHelper():
1692+ """
1693+ OpenOffice helper methods.
1694+
1695+ Loads and saves OpenOffice documents, doing the needed format conversions.
1696+ Also lets you to replace text (placeholders) on documents with the contents
1697+ of another document.
1698+
1699+ Uses PyUNO, requires OpenOffice to be installed on the computer,
1700+ and a OpenOffice instance listening on the given port
1701+ (or it may start a headless OpenOffice instance for you).
1702+
1703+ Based on PyODConverter (http://www.artofsolving.com/opensource/pyodconverter)
1704+ """
1705+
1706+ # OpenOffice main executable posible paths
1707+ OOPATHS = [ '/usr/bin/soffice', '/usr/lib64/ooo-2.0/program/soffice', '/opt/openoffice.org3/program/soffice', 'C:\\Program Files\\OpenOffice.org 3.1\\program\\soffice', ]
1708+
1709+
1710+ #
1711+ # Import/export formats and filter options
1712+ #
1713+ # see http://wiki.services.openoffice.org/wiki/Framework/Article/Filter
1714+ #
1715+
1716+ #
1717+ # Import filter options (only formats that require options)
1718+ #
1719+ IMPORT_FILTER_MAP = {
1720+ 'txt': { 'FilterName': 'Text (encoded)', 'FilterOptions': 'utf8' },
1721+ 'csv': { 'FilterName': 'Text - txt - csv (StarCalc)', 'FilterOptions': '44,34,0' }
1722+ }
1723+
1724+ #
1725+ # Export filter mapping
1726+ #
1727+ EXPORT_FILTER_MAPS = {
1728+ 'text': {
1729+ 'pdf': { "FilterName": "writer_pdf_Export" },
1730+ 'html': { "FilterName": "HTML (StarWriter)" },
1731+ 'odt': { "FilterName": "writer8" },
1732+ 'doc': { "FilterName": "MS Word 97" },
1733+ 'rtf': { "FilterName": "Rich Text Format" },
1734+ 'txt': { "FilterName": "Text", "FilterOptions": "utf8" }
1735+ },
1736+ 'web': {
1737+ 'pdf': { "FilterName": "writer_web_pdf_Export" },
1738+ 'odt': { "FilterName": "writerweb8_writer" },
1739+ },
1740+ 'spreadsheet': {
1741+ 'pdf': { "FilterName": "calc_pdf_Export" },
1742+ 'html': { "FilterName": "HTML (StarCalc)" },
1743+ 'ods': { "FilterName": "calc8" },
1744+ 'xls': { "FilterName": "MS Excel 97" },
1745+ 'csv': { "FilterName": "Text - txt - csv (StarCalc)", "FilterOptions": "44,34,0" }
1746+ },
1747+ 'presentation': {
1748+ 'pdf': { "FilterName": "impress_pdf_Export" },
1749+ 'html': { "FilterName": "impress_html_Export" },
1750+ 'odp': { "FilterName": "impress8" },
1751+ 'ppt': { "FilterName": "MS PowerPoint 97" },
1752+ 'ppt': { "FilterName": "impress_flash_Export" },
1753+ },
1754+ 'drawing': {
1755+ 'pdf': { "FilterName": "draw_pdf_Export" },
1756+ 'swf': { "FilterName": "draw_flash_Export" },
1757+ }
1758+ }
1759+
1760+
1761+ #
1762+ # Code ---------------------------------------------------------------------
1763+ #
1764+
1765+ def log(self, message):
1766+ """
1767+ Helper method used print debug messages
1768+ """
1769+ if self.logger:
1770+ self.logger(message)
1771+ else:
1772+ print "OOHelper: %s" % message
1773+
1774+
1775+ def __init__(self, openoffice_port=8100, autostart_openoffice=True, logger=None):
1776+ """
1777+ Initialize the default values and try to connect to OpenOffice
1778+ (or even start it).
1779+ """
1780+ import uno
1781+
1782+ self.logger = logger
1783+
1784+ self.port = openoffice_port
1785+ self.autostart = autostart_openoffice
1786+
1787+ #
1788+ # Try to connect with retries (to start OpenOffice if autostart_openoffice is enabled)
1789+ #
1790+ retry = 2
1791+ while retry:
1792+ retry = retry - 1
1793+ try:
1794+ self.log("Connecting to OpenOffice...")
1795+ local_component_context = uno.getComponentContext()
1796+ resolver = local_component_context.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local_component_context)
1797+ component_context = resolver.resolve("uno:socket,host=localhost,port=%s;urp;StarOffice.ComponentContext" % self.port)
1798+ self.desktop = component_context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", component_context)
1799+ self.log("...connected.")
1800+ except Exception, ex:
1801+ #
1802+ # Assume that the connection to OpenOffice has failed
1803+ # because OpenOffice is not running or listening
1804+ # and try to start it if autostart_openoffice.
1805+ #
1806+ self.log("...connection to OpenOffice failed!")
1807+ if autostart_openoffice and retry:
1808+ #
1809+ # Try to start a headless OpenOffice server
1810+ #
1811+ ooffice = None
1812+ for path in self.OOPATHS:
1813+ if os.path.exists(path):
1814+ ooffice = path
1815+ break
1816+ if ooffice:
1817+ self.log("Starting headless OpenOffice listener on port %s..." % self.port)
1818+ subprocess.call([ooffice, '-headless', '-nofirststartwizard', '-accept=socket,host=localhost,port=%s;urp;' % self.port])
1819+ # Wait for OO to start
1820+ time.sleep(5)
1821+ self.log("...trying again...")
1822+ else:
1823+ raise OOHelperException(_("Couldn't connect to OpenOffice. Make sure you have an OpenOffice instance running and listening on the %s port. Details: %s") % (self.port, (hasattr(ex, 'value') and str(ex.value) or str(ex))))
1824+
1825+
1826+ def open_document(self, file_name):
1827+ """
1828+ Opens a document with OpenOffice
1829+ """
1830+ import uno
1831+ file_url = uno.systemPathToFileUrl(abspath(file_name))
1832+
1833+ if os.environ.get('OSTYPE', False) == 'FreeBSD':
1834+ # Workaround a problemas con OpenOffice 3.1 en FreeBSD
1835+ file_url = file_url.encode('UTF-8')
1836+
1837+ load_properties = { "Hidden": True }
1838+ file_ext = splitext(file_name)[1]
1839+ file_ext = file_ext and file_ext[1:].lower() or None
1840+ if self.IMPORT_FILTER_MAP.has_key(file_ext):
1841+ load_properties.update(self.IMPORT_FILTER_MAP[file_ext])
1842+
1843+ try:
1844+ document = self.desktop.loadComponentFromURL(file_url, "_blank", 0, self.make_properties(load_properties))
1845+ except Exception, ex:
1846+ raise OOHelperException(_("Error loading file %s with OpenOffice: %s") % (file_name, ex))
1847+ try:
1848+ document.refresh()
1849+ except AttributeError:
1850+ #print "Warning: Ignoring AttributeError on document refresh"
1851+ pass
1852+
1853+ return document
1854+
1855+
1856+ def save_document(self, document, file_name, close_document=True):
1857+ """
1858+ Saves a OpenOffice document to a file.
1859+ The file format will be detected (based on the file extension)
1860+ and the document will be converted to that format (see EXPORT_FILTER_MAPS).
1861+ """
1862+ import uno
1863+ file_url = uno.systemPathToFileUrl(abspath(file_name))
1864+
1865+ if os.environ.get('OSTYPE', False) == 'FreeBSD':
1866+ # Workaround a problemas con OpenOffice 3.1 en FreeBSD
1867+ file_url = file_url.encode('UTF-8')
1868+
1869+ save_properties = { }
1870+
1871+ #
1872+ # Get the export filter options for the given file extension
1873+ #
1874+ file_ext = splitext(file_name)[1]
1875+ file_ext = file_ext and file_ext[1:].lower() or None
1876+
1877+ export_filter_map = \
1878+ (document.supportsService("com.sun.star.text.WebDocument") and self.EXPORT_FILTER_MAPS['web']) \
1879+ or (document.supportsService("com.sun.star.text.GenericTextDocument") and self.EXPORT_FILTER_MAPS['text']) \
1880+ or (document.supportsService("com.sun.star.sheet.SpreadsheetDocument") and self.EXPORT_FILTER_MAPS['spreadsheet']) \
1881+ or (document.supportsService("com.sun.star.presentation.PresentationDocument") and self.EXPORT_FILTER_MAPS['presentation']) \
1882+ or (document.supportsService("com.sun.star.drawing.DrawingDocument") and self.EXPORT_FILTER_MAPS['drawing'])
1883+
1884+ if export_filter_map and export_filter_map.has_key(file_ext):
1885+ save_properties.update(export_filter_map[file_ext])
1886+
1887+ #
1888+ # Save the document
1889+ #
1890+ try:
1891+ document.storeToURL(file_url, self.make_properties(save_properties))
1892+ except Exception, ex:
1893+ raise OOHelperException(_("Error saving file %s with OpenOffice: %s") % (file_name, ex))
1894+ finally:
1895+ if close_document:
1896+ document.close(True)
1897+
1898+
1899+
1900+ def replace_text_with_file_contents(self, document, placeholder_text, file_name):
1901+ """
1902+ Inserts the given file into the current document.
1903+ The file contents will replace the placeholder text.
1904+ """
1905+ import uno
1906+ file_url = uno.systemPathToFileUrl(abspath(file_name))
1907+
1908+ search = document.createSearchDescriptor()
1909+ search.SearchString = placeholder_text
1910+
1911+ found = document.findFirst( search )
1912+ while found:
1913+ try:
1914+ found.insertDocumentFromURL(file_url, ())
1915+ except Exception, ex:
1916+ raise OOHelperException(_("Error inserting file %s on the OpenOffice document: %s") % (file_name, ex))
1917+ found = document.findNext(found, search)
1918+
1919+
1920+ def make_properties(self, properties_dict):
1921+ """
1922+ Helper to create a tuple of PropertyValue items from a dictionary.
1923+ """
1924+ import uno
1925+ props = []
1926+ for key in properties_dict:
1927+ prop = uno.createUnoStruct("com.sun.star.beans.PropertyValue")
1928+ prop.Name = key
1929+ prop.Value = properties_dict[key]
1930+ props.append(prop)
1931+ return tuple(props)
1932+
1933+
1934+
1935
1936=== added file 'pxgo_openoffice_reports/openoffice_report.py'
1937--- pxgo_openoffice_reports/openoffice_report.py 1970-01-01 00:00:00 +0000
1938+++ pxgo_openoffice_reports/openoffice_report.py 2010-11-02 09:27:47 +0000
1939@@ -0,0 +1,528 @@
1940+# -*- coding: utf-8 -*-
1941+# -*- encoding: utf-8 -*-
1942+##############################################################################
1943+#
1944+# OpenOffice Reports
1945+# Copyright (C) 2009 Pexego Sistemas Informáticos. All Rights Reserved
1946+# $Id$
1947+#
1948+# This program is free software: you can redistribute it and/or modify
1949+# it under the terms of the GNU General Public License as published by
1950+# the Free Software Foundation, either version 3 of the License, or
1951+# (at your option) any later version.
1952+#
1953+# This program is distributed in the hope that it will be useful,
1954+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1955+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1956+# GNU General Public License for more details.
1957+#
1958+# You should have received a copy of the GNU General Public License
1959+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1960+#
1961+##############################################################################
1962+
1963+"""
1964+OpenOffice Reports - Reporting Engine based on Relatorio and OpenOffice.
1965+"""
1966+__author__ = "Borja López Soilán (Pexego)"
1967+
1968+import os
1969+import report
1970+import pooler
1971+import netsvc
1972+import base64
1973+import tempfile
1974+import re
1975+from tools.translate import _
1976+from oo_template import OOTemplate, OOTemplateException
1977+import mx.DateTime
1978+from datetime import datetime
1979+import time
1980+
1981+DT_FORMAT = '%Y-%m-%d'
1982+DHM_FORMAT = '%Y-%m-%d %H:%M:%S'
1983+HM_FORMAT = '%H:%M:%S'
1984+
1985+
1986+class OOReportException(Exception):
1987+ """
1988+ OpenERP report exception
1989+ """
1990+ def __init__(self, message):
1991+ # pylint: disable-msg=W0231
1992+ self.message = message
1993+ def __str__(self):
1994+ return self.message
1995+
1996+
1997+class OOReport(object):
1998+ """
1999+ OpenOffice/Relatorio based report.
2000+ """
2001+
2002+ def log(self, message, level=netsvc.LOG_DEBUG):
2003+ """
2004+ Helper method used print debug messages
2005+ """
2006+ netsvc.Logger().notifyChannel('pxgo_openffice_reports', level, message)
2007+
2008+
2009+ def __init__(self, name, cr, uid, ids, data, context):
2010+ self.name = name
2011+ self.cr = cr
2012+ self.uid = uid
2013+ self.ids = ids
2014+ self.data = data
2015+ self.model = self.data['model']
2016+ self.context = context or {}
2017+ self.dbname = cr.dbname
2018+ self.pool = pooler.get_pool( cr.dbname )
2019+ self.openoffice_port = 8100
2020+ self.autostart_openoffice = True
2021+ self.lang_dict_called = False
2022+ self.lang_dict = {}
2023+ self.default_lang = {}
2024+ self._transl_regex = re.compile('(\[\[.+?\]\])')
2025+
2026+
2027+ def get_report_context(self):
2028+ """
2029+ Returns the context for the report
2030+ (Template method pattern)
2031+ """
2032+ return {}
2033+
2034+
2035+ def _get_lang_dict(self):
2036+ """
2037+ Helper function that returns a function that
2038+ sets the language for one object using the current database
2039+ connection (cr) and user (uid).
2040+ """
2041+ pool_lang = self.pool.get('res.lang')
2042+ lang = self.context.get('lang', False) or 'en_US'
2043+ lang_ids = pool_lang.search(self.cr, self.uid, [('code','=',lang)])[0]
2044+ lang_obj = pool_lang.browse(self.cr, self.uid, lang_ids)
2045+ self.lang_dict.update({'lang_obj':lang_obj,'date_format':lang_obj.date_format,'time_format':lang_obj.time_format})
2046+ self.default_lang[lang] = self.lang_dict.copy()
2047+ return True
2048+
2049+ def get_digits(self, obj=None, f=None, dp=None):
2050+ """gets value for digits attribute"""
2051+ d = DEFAULT_DIGITS = 2
2052+ if dp:
2053+ decimal_precision_obj = self.pool.get('decimal.precision')
2054+ ids = decimal_precision_obj.search(self.cr, self.uid, [('name', '=', dp)])
2055+ if ids:
2056+ d = decimal_precision_obj.browse(self.cr, self.uid, ids)[0].digits
2057+ elif obj and f:
2058+ res_digits = getattr(obj._columns[f], 'digits', lambda x: ((16, DEFAULT_DIGITS)))
2059+ if isinstance(res_digits, tuple):
2060+ d = res_digits[1]
2061+ else:
2062+ d = res_digits(self.cr)[1]
2063+ elif (hasattr(obj, '_field') and\
2064+ isinstance(obj._field, (float_class, function_class)) and\
2065+ obj._field.digits):
2066+ d = obj._field.digits[1] or DEFAULT_DIGITS
2067+ return d
2068+
2069+ def execute(self, output_format='pdf', report_file_name=None):
2070+ """
2071+ Generate the report.
2072+ """
2073+
2074+ def _base64_to_string(field_value):
2075+ """
2076+ Helper method to decode a binary field
2077+ """
2078+ return base64.decodestring(field_value)
2079+
2080+ def _get_attachments():
2081+ """
2082+ Helper function that returns a function that
2083+ gets the attachments for one object using the current database
2084+ connection (cr) and user (uid).
2085+ """
2086+ def get_attachments_func(browse_object):
2087+ """
2088+ Returns the attachments for one browse_object
2089+ """
2090+ db, pool = pooler.get_db_and_pool(self.dbname)
2091+ cr = db.cursor()
2092+ att_facade = pool.get('ir.attachment')
2093+ # pylint: disable-msg=W0212
2094+ attachment_ids = att_facade.search(cr, self.uid, [
2095+ ('res_model', '=', browse_object._name),
2096+ ('res_id', '=', browse_object.id)
2097+ ])
2098+ return att_facade.browse(cr, self.uid, attachment_ids)
2099+ return get_attachments_func
2100+
2101+ def _field_to_image(field_value, rotate=None):
2102+ """
2103+ Helper function that decodes and converts a binary field
2104+ into a png image and returns a tuple like the ones Relatorio
2105+ "image:" directive wants.
2106+ """
2107+ from PIL import Image
2108+ data = base64.decodestring(field_value)
2109+ dummy_fd, temp_file_name = tempfile.mkstemp(prefix='openerp_oor_f2i_')
2110+ temp_file = open(temp_file_name, 'wb')
2111+ try:
2112+ temp_file.write(data)
2113+ finally:
2114+ temp_file.close()
2115+ image = Image.open(temp_file_name)
2116+ if rotate:
2117+ image = image.rotate(rotate)
2118+ image.save(temp_file_name, 'png')
2119+ return (open(temp_file_name, 'rb'), 'image/png')
2120+
2121+
2122+ def _chart_template_to_image(field=None, filename=None, source=None, filepath=None, source_format=None, encoding=None, context=None):
2123+ """
2124+ Method that can be referenced from the template to include
2125+ charts as images.
2126+ When called it will process the file as a chart template,
2127+ generate a png image, and return the data plus the mime type.
2128+ """
2129+ # Field is a binary field with a base64 encoded file that we will
2130+ # use as source if it is specified
2131+ source = field and base64.decodestring(field) or source
2132+
2133+ filepath = filepath or filename
2134+ filename = None
2135+ assert filepath
2136+
2137+ #
2138+ # Search for the file on the addons folder of OpenERP if the
2139+ # filepath does not exist.
2140+ #
2141+ if not os.path.exists(filepath):
2142+ search_paths = ['./bin/addons/%s' % filepath, './addons/%s' % filepath]
2143+ for path in search_paths:
2144+ if os.path.exists(path):
2145+ filepath = path
2146+ break
2147+
2148+ #
2149+ # Genshi Base Template nor it's subclases
2150+ # (NewTextTemplate and chart.Template)
2151+ # seem to load the filepath/filename automatically;
2152+ # so we will read the file here if needed.
2153+ #
2154+ if not source:
2155+ file = open(filepath, 'rb')
2156+ try:
2157+ source = file.read()
2158+ finally:
2159+ file.close()
2160+
2161+ #
2162+ # Process the chart subreport file
2163+ #
2164+ self.log("Generating chart subreport...")
2165+ from relatorio.templates.chart import Template
2166+ chart_subreport_template = Template(source=source, encoding=encoding)
2167+ data = chart_subreport_template #.generate(**context)
2168+ self.log("...done, chart generated.")
2169+
2170+ return (data, 'image/png')
2171+
2172+
2173+ def _formatLang():
2174+ """
2175+ Helper function that returns a function that
2176+ formats received value to the language format.
2177+ """
2178+ def _format_lang(value, digits=None, date=False, date_time=False, grouping=True, monetary=False, dp=False):
2179+ """
2180+ Assuming 'Account' decimal.precision=3:
2181+ formatLang(value) -> digits=2 (default)
2182+ formatLang(value, digits=4) -> digits=4
2183+ formatLang(value, dp='Account') -> digits=3
2184+ formatLang(value, digits=5, dp='Account') -> digits=5
2185+ """
2186+ if digits is None:
2187+ if dp:
2188+ digits = self.get_digits(dp=dp)
2189+ else:
2190+ digits = self.get_digits(value)
2191+
2192+ if isinstance(value, (str, unicode)) and not value:
2193+ return ''
2194+
2195+ if not self.lang_dict_called:
2196+ self._get_lang_dict()
2197+ self.lang_dict_called = True
2198+
2199+ if date or date_time:
2200+ if not str(value):
2201+ return ''
2202+
2203+ date_format = self.lang_dict['date_format']
2204+ parse_format = DT_FORMAT
2205+ if date_time:
2206+ value=value.split('.')[0]
2207+ date_format = date_format + " " + self.lang_dict['time_format']
2208+ parse_format = DHM_FORMAT
2209+ if not isinstance(value, time.struct_time):
2210+ return time.strftime(date_format, time.strptime(value, parse_format))
2211+
2212+ if not isinstance(value, time.struct_time):
2213+ try:
2214+ date = mx.DateTime.strptime(str(value),parse_format)
2215+ except:# sometimes it takes converted values into value, so we dont need conversion.
2216+ return str(value)
2217+ else:
2218+ date = datetime(*value.timetuple()[:6])
2219+ return date.strftime(date_format)
2220+
2221+ return self.lang_dict['lang_obj'].format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
2222+ return _format_lang
2223+
2224+
2225+ def _format(text, oldtag=None):
2226+ """
2227+ Removes white spaces
2228+ """
2229+ return text.strip()
2230+
2231+
2232+ def translate():
2233+ def _translate(text):
2234+ lang = self.context['lang']
2235+ if lang and text and not text.isspace():
2236+ transl_obj = self.pool.get('ir.translation')
2237+ piece_list = self._transl_regex.split(text)
2238+ for pn in range(len(piece_list)):
2239+ if not self._transl_regex.match(piece_list[pn]):
2240+ source_string = piece_list[pn].replace('\n', ' ').strip()
2241+ if len(source_string):
2242+ translated_string = transl_obj._get_source(self.cr, self.uid, self.name, ('report', 'rml'), lang, source_string)
2243+ if translated_string:
2244+ piece_list[pn] = piece_list[pn].replace(source_string, translated_string)
2245+ text = ''.join(piece_list)
2246+ return text
2247+ return _translate
2248+
2249+
2250+ def set_html_image():
2251+ def _set_htmlImage(id, model=None, field=None, context=None):
2252+ if not id :
2253+ return ''
2254+ if not model:
2255+ model = 'ir.attachment'
2256+ try :
2257+ id = int(id)
2258+ res = self.pool.get(model).read(self.cr,self.uid,id)
2259+ if field :
2260+ return res[field]
2261+ elif model =='ir.attachment' :
2262+ return res['datas']
2263+ else:
2264+ return ''
2265+ except Exception,e:
2266+ return ''
2267+
2268+ return _set_htmlImage
2269+
2270+ def setLang():
2271+ """set lang to context"""
2272+ self.context['lang'] = lang
2273+ self.lang_dict_called = False
2274+
2275+
2276+
2277+ assert output_format
2278+
2279+ #
2280+ # Get the report path
2281+ #
2282+ if not report_file_name:
2283+ reports = self.pool.get( 'ir.actions.report.xml' )
2284+ report_ids = reports.search(self.cr, self.uid, [('report_name', '=', self.name[7:])], context=self.context)
2285+ report_file_name = reports.read(self.cr, self.uid, report_ids[0], ['report_rml'])['report_rml']
2286+ path = os.path.dirname(os.path.abspath(os.path.dirname(__file__)))
2287+ report_file_name = os.path.join(path, report_file_name)
2288+
2289+ #
2290+ # Set the variables that the report must see
2291+ #
2292+ context = self.context
2293+ context['objects'] = self.pool.get(self.model).browse(self.cr, self.uid, self.ids, self.context)
2294+ context['ids'] = self.ids
2295+ context['model'] = self.model
2296+ context['data'] = self.data
2297+
2298+ #
2299+ # Some aliases used on standard OpenERP reports
2300+ #
2301+ user = self.pool.get('res.users').browse(self.cr, self.uid, self.uid, self.context)
2302+ context['user'] = user
2303+ context['company'] = user.company_id
2304+ context['logo'] = user.company_id and user.company_id.logo
2305+ context['lang'] = context.get('lang') or (user.company_id and user.company_id.partner_id and user.company_id.partner_id.lang)
2306+
2307+ #
2308+ # Add some helper function aliases
2309+ #
2310+ context['base64_to_string'] = context.get('base64_to_string') or _base64_to_string
2311+ context['b2s'] = context.get('b2s') or _base64_to_string
2312+ context['get_attachments'] = context.get('get_attachments') or _get_attachments()
2313+ context['field_to_image'] = context.get('field_to_image') or _field_to_image
2314+ context['f2i'] = context.get('f2i') or _field_to_image
2315+ context['chart_template_to_image'] = context.get('chart_template_to_image') or _chart_template_to_image
2316+ context['chart'] = context.get('chart') or _chart_template_to_image
2317+ context['translate'] = context.get('translate') or translate()
2318+ context['_'] = context.get('_') or translate()
2319+ context['formatLang'] = context.get('formatLang') or _formatLang()
2320+ context['format'] = context.get('format') or _format
2321+ context['setHtmlImage'] = context.get('setHtmlImage') or set_html_image()
2322+ context['time'] = context.get('time') or time
2323+ context['setLang'] = context.get('setLang') or setLang
2324+
2325+ # Update the context with the custom report context
2326+ context.update(self.get_report_context())
2327+
2328+ #
2329+ # Process the template using the OpenOffice/Relatorio engine
2330+ #
2331+ data = self.process_template(report_file_name, output_format, context)
2332+
2333+ return data
2334+
2335+ def process_template(self, template_file, output_format, context=None):
2336+ """
2337+ Will process a relatorio template and return the name
2338+ of the temp output file.
2339+ """
2340+ if context is None: context = {}
2341+ #
2342+ # Get the template
2343+ #
2344+ self.log("Loading template %s from %s" % (self.name, template_file))
2345+ try:
2346+ template = OOTemplate(source=None,
2347+ filepath=template_file,
2348+ output_format=output_format,
2349+ openoffice_port=self.openoffice_port,
2350+ autostart_openoffice=self.autostart_openoffice,
2351+ logger=self.log)
2352+ except OOTemplateException, ex:
2353+ raise OOReportException(_("Error loading the OpenOffice template: %s") % ex)
2354+
2355+ #
2356+ # Process the template
2357+ #
2358+ self.log("Rendering template %s as %s" % (self.name, output_format))
2359+ try:
2360+ data = template.oo_render(context=context)
2361+ except OOTemplateException, ex:
2362+ raise OOReportException(_("Error processing the OpenOffice template: %s") % ex)
2363+
2364+ return data
2365+
2366+
2367+
2368+class openoffice_report(report.interface.report_int):
2369+ """
2370+ Registers an OpenOffice/Relatorio report.
2371+ """
2372+
2373+ def __init__(self, name, model, parser=None, context=None):
2374+ if context is None: context = {}
2375+ # Remove report name from list of services if it already
2376+ # exists to avoid report_int's assert. We want to keep the
2377+ # automatic registration at login, but at the same time we
2378+ # need modules to be able to use a parser for certain reports.
2379+ if not name.startswith('report.'):
2380+ name = 'report.' + name
2381+ if name in netsvc.Service._services:
2382+ del netsvc.Service._services[name]
2383+ super(openoffice_report, self).__init__(name)
2384+
2385+ self.model = model
2386+ self.parser = parser
2387+ self._context = context
2388+
2389+ def create(self, cr, uid, ids, datas, context=None):
2390+ """
2391+ Register the report with this handler.
2392+ """
2393+ name = self.name
2394+
2395+ reportClass = self.parser or OOReport
2396+
2397+
2398+ self._context.update(context)
2399+
2400+ #
2401+ # Find the output format
2402+ #
2403+ reports = pooler.get_pool(cr.dbname).get( 'ir.actions.report.xml' )
2404+ report_ids = reports.search(cr, uid, [('report_name', '=', name[7:])], context=context)
2405+ report_type = reports.read(cr, uid, report_ids[0], ['report_type'])['report_type']
2406+ if report_type.startswith('oo-'):
2407+ output_format = report_type.split('-')[1]
2408+ else:
2409+ output_format = 'pdf'
2410+
2411+ #
2412+ # Get the report
2413+ #
2414+ rpt = reportClass( name, cr, uid, ids, datas, self._context )
2415+ return (rpt.execute(output_format=output_format), output_format )
2416+
2417+
2418+#Allow call to old create method
2419+report.report_sxw.report_sxw.old_create = report.report_sxw.report_sxw.create
2420+
2421+def create(self, cr, uid, ids, data, context=None):
2422+ """
2423+ Wrapper around the create method of report_sxw
2424+ that registers 'automagically' OpenOffice reports.
2425+ """
2426+ if context is None: context = {}
2427+
2428+ if self.internal_header:
2429+ context.update({'internal_header': self.internal_header})
2430+ pool = pooler.get_pool(cr.dbname)
2431+ ir_obj = pool.get('ir.actions.report.xml')
2432+ report_xml_ids = ir_obj.search(cr, uid,
2433+ [('report_name', '=', self.name[7:])], context=context)
2434+
2435+ fnct_ret = False
2436+
2437+ if report_xml_ids:
2438+ report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)
2439+ else:
2440+ title = ''
2441+ report_type= data.get('report_type', 'pdf')
2442+
2443+ if not report_type.startswith('oo-'):
2444+ fnct_ret = self.old_create(cr, uid, ids, data, context=context)
2445+ else:
2446+ rml = tools.file_open(self.tmpl, subdir=None).read()
2447+
2448+ class a(object):
2449+ def __init__(self, *args, **argv):
2450+ for key,arg in argv.items():
2451+ setattr(self, key, arg)
2452+
2453+ report_xml = a(title=title, report_type=report_type, report_rml_content=rml, name=title, attachment=False, header=self.header)
2454+
2455+ report_xml.header = False
2456+
2457+ if not fnct_ret:
2458+ oo_report = openoffice_report(self.name, data['model'], context=context)
2459+ fnct_ret = oo_report.create(cr, uid, ids, data, context)
2460+ if not fnct_ret:
2461+ return (False,False)
2462+
2463+ return fnct_ret
2464+
2465+#override create method
2466+report.report_sxw.report_sxw.create = create
2467+
2468
2469=== added file 'pxgo_openoffice_reports/report_xml.py'
2470--- pxgo_openoffice_reports/report_xml.py 1970-01-01 00:00:00 +0000
2471+++ pxgo_openoffice_reports/report_xml.py 2010-11-02 09:27:47 +0000
2472@@ -0,0 +1,189 @@
2473+# -*- coding: utf-8 -*-
2474+# -*- encoding: utf-8 -*-
2475+##############################################################################
2476+#
2477+# OpenOffice Reports
2478+# Copyright (C) 2009 Pexego Sistemas Informáticos. All Rights Reserved
2479+# $Id$
2480+#
2481+# This program is free software: you can redistribute it and/or modify
2482+# it under the terms of the GNU General Public License as published by
2483+# the Free Software Foundation, either version 3 of the License, or
2484+# (at your option) any later version.
2485+#
2486+# This program is distributed in the hope that it will be useful,
2487+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2488+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2489+# GNU General Public License for more details.
2490+#
2491+# You should have received a copy of the GNU General Public License
2492+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2493+#
2494+##############################################################################
2495+
2496+"""
2497+Extends report_xml to add new report types to the report_type selection.
2498+"""
2499+__author__ = "Borja López Soilán (Pexego)"
2500+
2501+import os
2502+import base64
2503+from osv import osv, fields
2504+import openoffice_report
2505+from tools.translate import _
2506+
2507+class report_xml_file(osv.osv):
2508+ _name = 'ir.actions.report.xml.file'
2509+ _columns = {
2510+ 'file': fields.binary('File', required=True, filters="*.odt,*.pdf,*.html,*.doc,*.rtf,*.txt,*.ods,*.xls,*.csv,*.odp,*.ppt,*.swf", help=''),
2511+ 'filename': fields.char('File Name', size=256, required=False, help=''),
2512+ 'report_id': fields.many2one('ir.actions.report.xml', 'Report', required=True, ondelete='cascade', help=''),
2513+ 'default': fields.boolean('Default', help=''),
2514+ }
2515+ def create(self, cr, uid, vals, context=None):
2516+ result = super(report_xml_file,self).create(cr, uid, vals, context)
2517+ self.pool.get('ir.actions.report.xml').update(cr, uid, [vals['report_id']], context)
2518+ return result
2519+
2520+ def write(self, cr, uid, ids, vals, context=None):
2521+ result = super(report_xml_file,self).write(cr, uid, ids, vals, context)
2522+ for attachment in self.browse(cr, uid, ids, context):
2523+ self.pool.get('ir.actions.report.xml').update(cr, uid, [attachment.report_id.id], context)
2524+ return result
2525+
2526+report_xml_file()
2527+
2528+class report_xml(osv.osv):
2529+ """
2530+ Extends report_xml to add new report types to the report_type selection.
2531+
2532+ You may declare reports of the new types like this
2533+ <report id="report_REPORTNAME"
2534+ ... />
2535+ <record model="ir.actions.report.xml" id="report_REPORTNAME">
2536+ <field name="report_type">oo-odt</field>
2537+ </record>
2538+ """
2539+
2540+ _inherit = 'ir.actions.report.xml'
2541+
2542+ _columns = {
2543+ 'report_type': fields.selection([
2544+ ('pdf', 'pdf'),
2545+ ('html', 'html'),
2546+ ('raw', 'raw'),
2547+ ('sxw', 'sxw'),
2548+ ('odt', 'odt'),
2549+ ('html2html','Html from html'),
2550+ ('oo-pdf', 'OpenOffice - pdf output'),
2551+ ('oo-html', 'OpenOffice - html output'),
2552+ ('oo-odt', 'OpenOffice - odt output'),
2553+ ('oo-doc', 'OpenOffice - doc output'),
2554+ ('oo-rtf', 'OpenOffice - rtf output'),
2555+ ('oo-txt', 'OpenOffice - txt output'),
2556+ ('oo-ods', 'OpenOffice - ods output'),
2557+ ('oo-xls', 'OpenOffice - xls output'),
2558+ ('oo-csv', 'OpenOffice - csv output'),
2559+ ('oo-odp', 'OpenOffice - odp output'),
2560+ ('oo-ppt', 'OpenOffice - ppt output'),
2561+ ('oo-swf', 'OpenOffice - swf output'),
2562+ ], string='Type', required=True),
2563+ 'openoffice_file_ids': fields.one2many('ir.actions.report.xml.file', 'report_id', 'Files', help=''),
2564+ 'openoffice_model_id': fields.many2one('ir.model', 'Model', help=''),
2565+ 'openoffice_report': fields.boolean('Is OpenOffice Report?', help=''),
2566+ }
2567+
2568+ def create(self, cr, uid, vals, context=None):
2569+ if context and context.get('openoffice_report'):
2570+ vals['model'] = self.pool.get('ir.model').browse(cr, uid, vals['openoffice_model_id'], context).model
2571+ vals['type'] = 'ir.actions.report.xml'
2572+# vals['report_type'] = 'pdf'
2573+ vals['openoffice_report'] = True
2574+ vals['header'] = False
2575+
2576+ return super(report_xml, self).create(cr, uid, vals, context)
2577+
2578+ def write(self, cr, uid, ids, vals, context=None):
2579+ if context and context.get('openoffice_report'):
2580+ if 'openoffice_model_id' in vals:
2581+ vals['model'] = self.pool.get('ir.model').browse(cr, uid, vals['openoffice_model_id'], context).model
2582+ vals['type'] = 'ir.actions.report.xml'
2583+# vals['report_type'] = 'pdf'
2584+ vals['openoffice_report'] = True
2585+ vals['header'] = False
2586+
2587+ return super(report_xml, self).write(cr, uid, ids, vals, context)
2588+
2589+ def unlink(self, cr, uid, ids, context=None):
2590+ """Deletes ir_values register when you delete any ir.actions.report.xml"""
2591+ if context is None: context = {}
2592+ for report in self.browse(cr, uid, ids):
2593+ values = self.pool.get('ir.values').search(cr, uid, [('value','=','ir.actions.report.xml,%s'% report.id)])
2594+ if values:
2595+ self.pool.get('ir.values').unlink(cr, uid, values)
2596+
2597+ return super(report_xml, self).unlink(cr, uid, ids, context=context)
2598+
2599+ def update(self, cr, uid, ids, context={}):
2600+ """Browse attachments and store .odt into pxgo_openoffixe_reprots/custom_reports
2601+ directory. Also add or update ir.values data so they're shown on model views."""
2602+ for report in self.browse(cr, uid, ids):
2603+ has_default = False
2604+
2605+ for attachment in report.openoffice_file_ids:
2606+ content = attachment.file
2607+ fileName = attachment.filename
2608+
2609+ if not fileName or not content:
2610+ continue
2611+
2612+ path = self.save_file( fileName, content )
2613+ for extension in ['.odt','.pdf','.html','.doc','.rtf','.txt','.ods','.xls','.csv','.odp','.ppt','.swf']:
2614+ if extension in fileName:
2615+ if attachment.default:
2616+ if has_default:
2617+ raise osv.except_osv(_('Error'), _('There is more than one report marked as default'))
2618+
2619+ has_default = True
2620+ # Update path into report_rml field.
2621+ self.write(cr, uid, [report.id], {
2622+ 'report_rml': path
2623+ })
2624+
2625+ valuesId = self.pool.get('ir.values').search(cr, uid, [('value','=','ir.actions.report.xml,%s'% report.id)])
2626+ data = {
2627+ 'name': report.name,
2628+ 'model': report.model,
2629+ 'key': 'action',
2630+ 'object': True,
2631+ 'key2': 'client_print_multi',
2632+ 'value': 'ir.actions.report.xml,%s'% report.id
2633+ }
2634+
2635+ if not valuesId:
2636+ valuesId = self.pool.get('ir.values').create(cr, uid, data, context=context)
2637+ else:
2638+ self.pool.get('ir.values').write(cr, uid, valuesId, data, context=context)
2639+ valuesId = valuesId[0]
2640+
2641+ if not has_default:
2642+ raise osv.except_osv(_('Error'), _('No report has been marked as default.'))
2643+
2644+ # Ensure the report is registered so it can be used immediately
2645+ openoffice_report.openoffice_report( report.report_name, report.model )
2646+
2647+ return True
2648+
2649+ def save_file(self, name, value):
2650+ """save the file to pxgo_openoffice_reports/custom_reports"""
2651+ path = os.path.abspath( os.path.dirname(__file__) )
2652+ path += '/custom_reports/%s' % name
2653+ f = open( path, 'wb+' )
2654+ try:
2655+ f.write( base64.decodestring( value ) )
2656+ finally:
2657+ f.close()
2658+ path = 'pxgo_openoffice_reports/custom_reports/%s' % name
2659+ return path
2660+
2661+report_xml()
2662
2663=== added file 'pxgo_openoffice_reports/report_xml_view.xml'
2664--- pxgo_openoffice_reports/report_xml_view.xml 1970-01-01 00:00:00 +0000
2665+++ pxgo_openoffice_reports/report_xml_view.xml 2010-11-02 09:27:47 +0000
2666@@ -0,0 +1,103 @@
2667+<?xml version="1.0"?>
2668+<openerp>
2669+<data>
2670+ <record id="act_report_xml_view" model="ir.ui.view">
2671+ <field name="name">ir.actions.report.xml.openoffice</field>
2672+ <field name="model">ir.actions.report.xml</field>
2673+ <field name="type">form</field>
2674+ <field name="inherit_id" ref="base.act_report_xml_view"/>
2675+ <field name="arch" type="xml">
2676+ <field name="report_name" position="after">
2677+ <button string="Update from attachments" name="update" type="object" colspan="2"/>
2678+ </field>
2679+ </field>
2680+ </record>
2681+
2682+ <record id="act_report_openoffice_file_form" model="ir.ui.view">
2683+ <field name="name">ir.actions.report.openoffice.file.form</field>
2684+ <field name="model">ir.actions.report.xml.file</field>
2685+ <field name="type">form</field>
2686+ <field name="arch" type="xml">
2687+ <form string="Openoffice Reports File">
2688+ <field name="file" filename="filename" colspan="4"/>
2689+ <field name="filename" colspan="4"/>
2690+ <field name="default" colspan="4"/>
2691+ </form>
2692+ </field>
2693+ </record>
2694+ <record id="act_report_openoffice_file_tree" model="ir.ui.view">
2695+ <field name="name">ir.actions.report.openoffice.file.tree</field>
2696+ <field name="model">ir.actions.report.xml.file</field>
2697+ <field name="type">tree</field>
2698+ <field name="arch" type="xml">
2699+ <tree string="Openoffice Reports File">
2700+ <field name="filename"/>
2701+ <field name="default"/>
2702+ </tree>
2703+ </field>
2704+ </record>
2705+
2706+ <record id="act_report_openoffice_form" model="ir.ui.view">
2707+ <field name="name">ir.actions.report.openoffice.form</field>
2708+ <field name="model">ir.actions.report.xml</field>
2709+ <field name="type">form</field>
2710+ <field name="priority">20</field>
2711+ <field name="arch" type="xml">
2712+ <form string="openoffice Reports">
2713+ <field name="name" select="1"/>
2714+ <field name="openoffice_model_id" required="True" select="1"/>
2715+ <field name="report_name" select="1"/>
2716+ <field name="report_type" required="True" select="1"/>
2717+<!-- <field name="attachment"/>-->
2718+<!-- <field name="attachment_use"/>-->
2719+ <separator string="Files" colspan="4"/>
2720+ <field name="openoffice_file_ids" colspan="4" nolabel="1" />
2721+ <separator string="Groups" colspan="4"/>
2722+ <field name="groups_id" colspan="4" nolabel="1" />
2723+ </form>
2724+ </field>
2725+ </record>
2726+
2727+ <record id="act_report_openoffice_tree" model="ir.ui.view">
2728+ <field name="name">ir.actions.report.openoffice.tree</field>
2729+ <field name="model">ir.actions.report.xml</field>
2730+ <field name="type">tree</field>
2731+ <field name="priority">20</field>
2732+ <field name="arch" type="xml">
2733+ <tree string="Openoffice Reports">
2734+ <field name="name"/>
2735+ <field name="openoffice_model_id"/>
2736+ <field name="report_name"/>
2737+ <field name="report_type"/>
2738+ <field name="attachment"/>
2739+ </tree>
2740+ </field>
2741+ </record>
2742+
2743+
2744+ <record id="ir_action_report_openoffice" model="ir.actions.act_window">
2745+ <field name="name">Openoffice Reports</field>
2746+ <field name="type">ir.actions.act_window</field>
2747+ <field name="res_model">ir.actions.report.xml</field>
2748+ <field name="view_type">form</field>
2749+ <field name="view_mode">tree,form</field>
2750+ <field name="context">{'openoffice_report': True}</field>
2751+ <field name="domain">[('openoffice_report','=',True)]</field>
2752+ </record>
2753+ <record id="ir_action_report_openoffice_view0" model="ir.actions.act_window.view">
2754+ <field name="act_window_id" ref="ir_action_report_openoffice"/>
2755+ <field name="view_mode">tree</field>
2756+ <field name="view_id" ref="act_report_openoffice_tree"/>
2757+ <field name="sequence">0</field>
2758+ </record>
2759+ <record id="ir_action_report_openoffice_view1" model="ir.actions.act_window.view">
2760+ <field name="act_window_id" ref="ir_action_report_openoffice"/>
2761+ <field name="view_mode">form</field>
2762+ <field name="view_id" ref="act_report_openoffice_form"/>
2763+ <field name="sequence">1</field>
2764+ </record>
2765+
2766+ <menuitem parent="base.menu_custom" name="OpenOffice Reports" id="openoffice_reports_menu"/>
2767+ <menuitem action="ir_action_report_openoffice" id="menu_ir_action_report_openoffice" parent="openoffice_reports_menu"/>
2768+</data>
2769+</openerp>
2770
2771=== added directory 'pxgo_openoffice_reports/security'
2772=== added file 'pxgo_openoffice_reports/security/ir.model.access.csv'
2773--- pxgo_openoffice_reports/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
2774+++ pxgo_openoffice_reports/security/ir.model.access.csv 2010-11-02 09:27:47 +0000
2775@@ -0,0 +1,3 @@
2776+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
2777+"access_ir_actions_report_xml_file_all","ir_actions_report_xml_file","model_ir_actions_report_xml_file",,1,0,0,0
2778+"access_ir_actions_report_xml_file_group_system","ir_actions_report_xml_file_group_system","model_ir_actions_report_xml_file","base.group_system",1,1,1,1
2779\ No newline at end of file

Subscribers

People subscribed via source and target branches