report_py3o_fusion_server: Add support for PDF Export options of libreoffice
parent
6aad905e0f
commit
bfd8543285
|
@ -6,7 +6,14 @@
|
|||
Py3o Report Engine - Fusion server support
|
||||
==========================================
|
||||
|
||||
This module was written to let a py3o fusion server handle format conversion instead of local libreoffice.
|
||||
This module was written to let a py3o fusion server handle format conversion instead of local libreoffice. If you install this module above the *report_py3o* module, you will have to deploy additionnal software components and run 3 daemons (libreoffice, py3o.fusion and py3o.renderserver). This additionnal complexiy comes with several advantages:
|
||||
|
||||
* much better performances (libreoffice runs permanently in the background, no need to spawn a new libreoffice instance upon every document conversion).
|
||||
* ability to configure PDF export options in Odoo. This will allow you to generate:
|
||||
* PDF forms
|
||||
* password-protected PDF documents
|
||||
* PDF/A documents (required by some electronic invoicing standards such as Factur-X)
|
||||
* watermarked PDF documents
|
||||
|
||||
Installation
|
||||
============
|
||||
|
@ -54,11 +61,11 @@ At the end, with the dependencies, you should have the following py3o python lib
|
|||
|
||||
% pip freeze | grep py3o
|
||||
py3o.formats==0.3
|
||||
py3o.fusion==0.8.7
|
||||
py3o.fusion==0.8.8
|
||||
py3o.renderclient==0.2
|
||||
py3o.renderers.juno==0.8
|
||||
py3o.renderserver==0.5.1
|
||||
py3o.template==0.9.11
|
||||
py3o.template==0.9.12
|
||||
py3o.types==0.1.1
|
||||
|
||||
Start the Py3o Fusion server:
|
||||
|
|
|
@ -20,11 +20,13 @@
|
|||
},
|
||||
'demo': [
|
||||
"demo/report_py3o.xml",
|
||||
"demo/py3o_pdf_options.xml",
|
||||
],
|
||||
'data': [
|
||||
"views/ir_report.xml",
|
||||
'security/ir.model.access.csv',
|
||||
'views/py3o_server.xml',
|
||||
'views/py3o_pdf_options.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="py3o_pdf_options_pdfa" model="py3o.pdf.options">
|
||||
<field name="name">PDF/A (for Factur-X invoices)</field>
|
||||
<field name="pdfa" eval="True"/>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
|
@ -2,5 +2,6 @@
|
|||
# Copyright 2017 Therp BV <http://therp.nl>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
from . import ir_actions_report_xml
|
||||
from . import py3o_pdf_options
|
||||
from . import py3o_report
|
||||
from . import py3o_server
|
||||
|
|
|
@ -39,3 +39,7 @@ class IrActionsReportXml(models.Model):
|
|||
py3o_server_id = fields.Many2one(
|
||||
"py3o.server",
|
||||
"Fusion Server")
|
||||
pdf_options_id = fields.Many2one(
|
||||
'py3o.pdf.options', string='PDF Options', ondelete='restrict',
|
||||
help="PDF options can be set per report, but also per Py3o Server. "
|
||||
"If both are defined, the options on the report are used.")
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2018 Akretion (http://www.akretion.com)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Py3oPdfOptions(models.Model):
|
||||
_name = 'py3o.pdf.options'
|
||||
_description = 'Define PDF export options for Libreoffice'
|
||||
|
||||
name = fields.Char(required=True)
|
||||
# GENERAL TAB
|
||||
# UseLosslessCompression (bool)
|
||||
image_compression = fields.Selection([
|
||||
('lossless', 'Lossless Compression'),
|
||||
('jpeg', 'JPEG Compression'),
|
||||
], string='Image Compression', default='jpeg')
|
||||
# Quality (int)
|
||||
image_jpeg_quality = fields.Integer(
|
||||
string='Image JPEG Quality', default=90,
|
||||
help="Enter a percentage between 0 and 100.")
|
||||
# ReduceImageResolution (bool) and MaxImageResolution (int)
|
||||
image_reduce_resolution = fields.Selection([
|
||||
('none', 'Disable'),
|
||||
('75', '75 DPI'),
|
||||
('150', '150 DPI'),
|
||||
('300', '300 DPI'),
|
||||
('600', '600 DPI'),
|
||||
('1200', '1200 DPI'),
|
||||
], string='Reduce Image Resolution', default='300')
|
||||
watermark = fields.Boolean('Sign With Watermark')
|
||||
# Watermark (string)
|
||||
watermark_text = fields.Char('WaterMark Text')
|
||||
# UseTaggedPDF (bool)
|
||||
tagged_pdf = fields.Boolean('Tagged PDF (add document structure)')
|
||||
# SelectPdfVersion (int)
|
||||
# 0 = PDF 1.4 (default selection).
|
||||
# 1 = PDF/A-1 (ISO 19005-1:2005)
|
||||
pdfa = fields.Boolean(
|
||||
'Archive PDF/A-1a (ISO 19005-1)',
|
||||
help="If you enable this option, you will not be able to "
|
||||
"password-protect the document or apply other security settings.")
|
||||
# ExportFormFields (bool)
|
||||
pdf_form = fields.Boolean('Create PDF Form', default=True)
|
||||
# FormsType (int)
|
||||
pdf_form_format = fields.Selection([
|
||||
('0', 'FDF'),
|
||||
('1', 'PDF'),
|
||||
('2', 'HTML'),
|
||||
('3', 'XML'),
|
||||
], string='Submit Format', default='0')
|
||||
# AllowDuplicateFieldNames (bool)
|
||||
pdf_form_allow_duplicate = fields.Boolean('Allow Duplicate Field Names')
|
||||
# ExportBookmarks (bool)
|
||||
export_bookmarks = fields.Boolean('Export Bookmarks', default=True)
|
||||
# ExportPlaceholders (bool)
|
||||
export_placeholders = fields.Boolean('Export Placeholders', default=True)
|
||||
# ExportNotes (bool)
|
||||
export_comments = fields.Boolean('Export Comments')
|
||||
# ExportHiddenSlides (bool) ??
|
||||
export_hidden_slides = fields.Boolean(
|
||||
'Export Automatically Insered Blank Pages')
|
||||
# Doesn't make sense to have the option "View PDF after export" ! :)
|
||||
# INITIAL VIEW TAB
|
||||
# InitialView (int)
|
||||
initial_view = fields.Selection([
|
||||
('0', 'Page Only'),
|
||||
('1', 'Bookmarks and Page'),
|
||||
('2', 'Thumnails and Page'),
|
||||
], string='Panes', default='0')
|
||||
# InitialPage (int)
|
||||
initial_page = fields.Integer(string='Initial Page', default=1)
|
||||
# Magnification (int)
|
||||
magnification = fields.Selection([
|
||||
('0', 'Default'),
|
||||
('1', 'Fit in Window'),
|
||||
('2', 'Fit Width'),
|
||||
('3', 'Fit Visible'),
|
||||
('4', 'Zoom'),
|
||||
], string='Magnification', default='0')
|
||||
# Zoom (int)
|
||||
zoom = fields.Integer(
|
||||
string='Zoom Factor', default=100,
|
||||
help='Possible values: from 50 to 1600')
|
||||
# PageLayout (int)
|
||||
page_layout = fields.Selection([
|
||||
('0', 'Default'),
|
||||
('1', 'Single Page'),
|
||||
('2', 'Continuous'),
|
||||
('3', 'Continuous Facing'),
|
||||
], string='Page Layout', default='0')
|
||||
# USER INTERFACE TAB
|
||||
# ResizeWindowToInitialPage (bool)
|
||||
resize_windows_initial_page = fields.Boolean(
|
||||
string='Resize Windows to Initial Page')
|
||||
# CenterWindow (bool)
|
||||
center_window = fields.Boolean(string='Center Window on Screen')
|
||||
# OpenInFullScreenMode (bool)
|
||||
open_fullscreen = fields.Boolean(string='Open in Full Screen Mode')
|
||||
# DisplayPDFDocumentTitle (bool)
|
||||
display_document_title = fields.Boolean(string='Display Document Title')
|
||||
# HideViewerMenubar (bool)
|
||||
hide_menubar = fields.Boolean(string='Hide Menubar')
|
||||
# HideViewerToolbar (bool)
|
||||
hide_toolbar = fields.Boolean(string='Hide Toolbar')
|
||||
# HideViewerWindowControls (bool)
|
||||
hide_window_controls = fields.Boolean(string='Hide Windows Controls')
|
||||
# OpenBookmarkLevels (int) -1 = all (default) from 1 to 10
|
||||
open_bookmark_levels = fields.Selection([
|
||||
('-1', 'All Levels'),
|
||||
('1', '1'),
|
||||
('2', '2'),
|
||||
('3', '3'),
|
||||
('4', '4'),
|
||||
('5', '5'),
|
||||
('6', '6'),
|
||||
('7', '7'),
|
||||
('8', '8'),
|
||||
('9', '9'),
|
||||
('10', '10'),
|
||||
], default='-1', string='Visible Bookmark Levels')
|
||||
# LINKS TAB
|
||||
# ExportBookmarksToPDFDestination (bool)
|
||||
export_bookmarks_named_dest = fields.Boolean(
|
||||
string='Export Bookmarks as Named Destinations')
|
||||
# ConvertOOoTargetToPDFTarget (bool)
|
||||
convert_doc_ref_to_pdf_target = fields.Boolean(
|
||||
string='Convert Document References to PDF Targets')
|
||||
# ExportLinksRelativeFsys (bool)
|
||||
export_filesystem_urls = fields.Boolean(
|
||||
string='Export URLs Relative to Filesystem')
|
||||
# PDFViewSelection -> mnDefaultLinkAction (int)
|
||||
cross_doc_link_action = fields.Selection([
|
||||
('0', 'Default'),
|
||||
('1', 'Open with PDF Reader Application'),
|
||||
('2', 'Open with Internet Browser'),
|
||||
], string='Cross-document Links', default='default')
|
||||
# SECURITY TAB
|
||||
# EncryptFile (bool)
|
||||
encrypt = fields.Boolean('Encrypt')
|
||||
# DocumentOpenPassword (char)
|
||||
document_password = fields.Char(string='Document Password')
|
||||
# RestrictPermissions (bool)
|
||||
restrict_permissions = fields.Boolean('Restrict Permissions')
|
||||
# PermissionPassword (char)
|
||||
permission_password = fields.Char(string='Permission Password')
|
||||
# TODO PreparedPasswords + PreparedPermissionPassword
|
||||
# I don't see those fields in the LO interface !
|
||||
# But they are used in the LO code...
|
||||
# Printing (int)
|
||||
printing = fields.Selection([
|
||||
('0', 'Not Permitted'),
|
||||
('1', 'Low Resolution (150 dpi)'),
|
||||
('2', 'High Resolution'),
|
||||
], string='Printing', default='2')
|
||||
# Changes (int)
|
||||
changes = fields.Selection([
|
||||
('0', 'Not Permitted'),
|
||||
('1', 'Inserting, Deleting and Rotating Pages'),
|
||||
('2', 'Filling in Form Fields'),
|
||||
('3', 'Commenting, Filling in Form Fields'),
|
||||
('4', 'Any Except Extracting Pages'),
|
||||
], string='Changes', default='4')
|
||||
# EnableCopyingOfContent (bool)
|
||||
content_copying_allowed = fields.Boolean(
|
||||
string='Enable Copying of Content', default=True)
|
||||
# EnableTextAccessForAccessibilityTools (bool)
|
||||
text_access_accessibility_tools_allowed = fields.Boolean(
|
||||
string='Enable Text Access for Accessibility Tools', default=True)
|
||||
# DIGITAL SIGNATURE TAB
|
||||
# This will be possible but not easy
|
||||
# Because the certificate parameter is a pointer to a certificate
|
||||
# already registered in LO
|
||||
# On Linux LO reuses the Mozilla certificate store (on Windows the
|
||||
# one from Windows)
|
||||
# But there seems to be some possibilities to send this certificate via API
|
||||
# It seems you can add temporary certificates during runtime:
|
||||
# https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1security_1_1XCertificateContainer.html
|
||||
# Here is an API to retrieve the known certificates:
|
||||
# https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1xml_1_1crypto_1_1XSecurityEnvironment.html
|
||||
# Thanks to 'samuel_m' on libreoffice-dev IRC chan for pointing me to this
|
||||
|
||||
@api.constrains(
|
||||
'image_jpeg_quality', 'initial_page', 'pdfa',
|
||||
'cross_doc_link_action', 'magnification', 'zoom')
|
||||
def check_pdf_options(self):
|
||||
for opt in self:
|
||||
if opt.image_jpeg_quality > 100 or opt.image_jpeg_quality < 1:
|
||||
raise ValidationError(_(
|
||||
"The parameter Image JPEG Quality must be between 1 %%"
|
||||
" and 100 %% (current value: %s %%)")
|
||||
% opt.image_jpeg_quality)
|
||||
if opt.initial_page < 1:
|
||||
raise ValidationError(_(
|
||||
"The initial page parameter must be strictly positive "
|
||||
"(current value: %d)") % opt.initial_page)
|
||||
if opt.pdfa and opt.cross_doc_link_action == '1':
|
||||
raise ValidationError(_(
|
||||
"The PDF/A option is not compatible with "
|
||||
"'Cross-document Links' = "
|
||||
"'Open with PDF Reader Application'."))
|
||||
if opt.magnification == '4' and (opt.zoom < 50 or opt.zoom > 1600):
|
||||
raise ValidationError(_(
|
||||
"The value of the zoom factor must be between 50 and 1600 "
|
||||
"(current value: %d)") % opt.zoom)
|
||||
|
||||
@api.onchange('encrypt')
|
||||
def encrypt_change(self):
|
||||
if not self.encrypt:
|
||||
self.document_password = False
|
||||
|
||||
@api.onchange('restrict_permissions')
|
||||
def restrict_permissions_change(self):
|
||||
if not self.restrict_permissions:
|
||||
self.permission_password = False
|
||||
|
||||
@api.onchange('pdfa')
|
||||
def pdfa_change(self):
|
||||
if self.pdfa:
|
||||
self.pdf_form = False
|
||||
self.encrypt = False
|
||||
self.restrict_permissions = False
|
||||
|
||||
def odoo2libreoffice_options(self):
|
||||
self.ensure_one()
|
||||
options = {}
|
||||
# GENERAL TAB
|
||||
if self.image_compression == 'lossless':
|
||||
options['UseLosslessCompression'] = True
|
||||
else:
|
||||
options['UseLosslessCompression'] = False
|
||||
options['Quality'] = self.image_jpeg_quality
|
||||
if self.image_reduce_resolution != 'none':
|
||||
options['ReduceImageResolution'] = True
|
||||
options['MaxImageResolution'] = int(self.image_reduce_resolution)
|
||||
else:
|
||||
options['ReduceImageResolution'] = False
|
||||
if self.watermark and self.watermark_text:
|
||||
options['Watermark'] = self.watermark_text
|
||||
if self.pdfa:
|
||||
options['SelectPdfVersion'] = 1
|
||||
options['UseTaggedPDF'] = self.tagged_pdf
|
||||
else:
|
||||
options['SelectPdfVersion'] = 0
|
||||
if self.pdf_form and self.pdf_form_format and not self.pdfa:
|
||||
options['ExportFormFields'] = True
|
||||
options['FormsType'] = int(self.pdf_form_format)
|
||||
options['AllowDuplicateFieldNames'] = self.pdf_form_allow_duplicate
|
||||
else:
|
||||
options['ExportFormFields'] = False
|
||||
|
||||
options.update({
|
||||
'ExportBookmarks': self.export_bookmarks,
|
||||
'ExportPlaceholders': self.export_placeholders,
|
||||
'ExportNotes': self.export_comments,
|
||||
'ExportHiddenSlides': self.export_hidden_slides,
|
||||
})
|
||||
|
||||
# INITIAL VIEW TAB
|
||||
options.update({
|
||||
'InitialView': int(self.initial_view),
|
||||
'InitialPage': self.initial_page,
|
||||
'Magnification': int(self.magnification),
|
||||
'PageLayout': int(self.page_layout),
|
||||
})
|
||||
|
||||
if self.magnification == '4':
|
||||
options['Zoom'] = self.zoom
|
||||
|
||||
# USER INTERFACE TAB
|
||||
options.update({
|
||||
'ResizeWindowToInitialPage': self.resize_windows_initial_page,
|
||||
'CenterWindow': self.center_window,
|
||||
'OpenInFullScreenMode': self.open_fullscreen,
|
||||
'DisplayPDFDocumentTitle': self.display_document_title,
|
||||
'HideViewerMenubar': self.hide_menubar,
|
||||
'HideViewerToolbar': self.hide_toolbar,
|
||||
'HideViewerWindowControls': self.hide_window_controls,
|
||||
})
|
||||
|
||||
if self.open_bookmark_levels:
|
||||
options['OpenBookmarkLevels'] = int(self.open_bookmark_levels)
|
||||
|
||||
# LINKS TAB
|
||||
options.update({
|
||||
'ExportBookmarksToPDFDestination':
|
||||
self.export_bookmarks_named_dest,
|
||||
'ConvertOOoTargetToPDFTarget': self.convert_doc_ref_to_pdf_target,
|
||||
'ExportLinksRelativeFsys': self.export_filesystem_urls,
|
||||
'PDFViewSelection': int(self.cross_doc_link_action),
|
||||
})
|
||||
|
||||
# SECURITY TAB
|
||||
if not self.pdfa:
|
||||
if self.encrypt and self.document_password:
|
||||
options['EncryptFile'] = True
|
||||
options['DocumentOpenPassword'] = self.document_password
|
||||
if self.restrict_permissions and self.permission_password:
|
||||
options.update({
|
||||
'RestrictPermissions': True,
|
||||
'PermissionPassword': self.permission_password,
|
||||
'Printing': int(self.printing),
|
||||
'Changes': int(self.changes),
|
||||
'EnableCopyingOfContent': self.content_copying_allowed,
|
||||
'EnableTextAccessForAccessibilityTools':
|
||||
self.text_access_accessibility_tools_allowed,
|
||||
})
|
||||
|
||||
logger.debug(
|
||||
'Py3o PDF options ID %s converted to %s', self.id, options)
|
||||
return options
|
|
@ -75,6 +75,12 @@ class Py3oReport(models.TransientModel):
|
|||
}
|
||||
if report_xml.py3o_is_local_fusion:
|
||||
fields['skipfusion'] = '1'
|
||||
if filetype == 'pdf':
|
||||
options = report_xml.pdf_options_id or\
|
||||
report_xml.py3o_server_id.pdf_options_id
|
||||
if options:
|
||||
pdf_options_dict = options.odoo2libreoffice_options()
|
||||
fields['pdf_options'] = json.dumps(pdf_options_dict)
|
||||
r = requests.post(
|
||||
report_xml.py3o_server_id.url, data=fields, files=files)
|
||||
if r.status_code != 200:
|
||||
|
|
|
@ -13,3 +13,7 @@ class Py3oServer(models.Model):
|
|||
help="If your Py3o Fusion server is on the same machine and runs "
|
||||
"on the default port, the URL is http://localhost:8765/form")
|
||||
is_active = fields.Boolean("Active", default=True)
|
||||
pdf_options_id = fields.Many2one(
|
||||
'py3o.pdf.options', string='PDF Options', ondelete='restrict',
|
||||
help="PDF options can be set per Py3o Server but also per report. "
|
||||
"If both are defined, the options on the report are used.")
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
access_py3o_server_admin,access_py3o_server_admin,model_py3o_server,base.group_no_one,1,1,1,1
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_py3o_server_admin,access_py3o_server_admin,model_py3o_server,base.group_system,1,1,1,1
|
||||
access_py3o_server_user,access_py3o_server_user,model_py3o_server,base.group_user,1,0,0,0
|
||||
access_py3o_pdf_options_admin,Full access to PDF options to Settings grp,model_py3o_pdf_options,base.group_system,1,1,1,1
|
||||
access_py3o_pdf_options_user,Read-only access to PDF options to employees,model_py3o_pdf_options,base.group_user,1,0,0,0
|
||||
|
|
|
|
@ -36,3 +36,8 @@ class TestReportPy3oFusionServer(test_report_py3o.TestReportPy3o):
|
|||
def test_reports_no_local_fusion(self):
|
||||
self.report.py3o_is_local_fusion = False
|
||||
self.test_reports()
|
||||
|
||||
def test_odoo2libreoffice_options(self):
|
||||
for options in self.env['py3o.pdf.options'].search([]):
|
||||
options_dict = options.odoo2libreoffice_options()
|
||||
self.assertIsInstance(options_dict, dict)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<field name="py3o_multi_in_one" position="after">
|
||||
<field name="py3o_is_local_fusion"/>
|
||||
<field name="py3o_server_id" />
|
||||
<field name="pdf_options_id" attrs="{'invisible': [('py3o_filetype', '!=', 'pdf')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="py3o_pdf_options_form" model="ir.ui.view">
|
||||
<field name="name">py3o.pdf.options.form</field>
|
||||
<field name="model">py3o.pdf.options</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Py3o PDF Export Options">
|
||||
<div class="oe_title">
|
||||
<label for="name"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="Give a name to the set of PDF export options"/>
|
||||
</h1>
|
||||
</div>
|
||||
<notebook>
|
||||
<page name="general" string="General">
|
||||
<group name="general">
|
||||
<group name="general-left" col="1">
|
||||
<group name="general-image" string="Image">
|
||||
<field name="image_compression" widget="radio"/>
|
||||
<label for="image_jpeg_quality" attrs="{'invisible': [('image_compression', '!=', 'jpeg')]}"/>
|
||||
<div name="image_jpeg_quality" attrs="{'invisible': [('image_compression', '!=', 'jpeg')]}">
|
||||
<field name="image_jpeg_quality" class="oe_inline"/>
|
||||
<label string=" %"/>
|
||||
</div>
|
||||
<field name="image_reduce_resolution"/>
|
||||
</group>
|
||||
<group name="general-watermark" string="Watermark">
|
||||
<field name="watermark"/>
|
||||
<field name="watermark_text" attrs="{'invisible': [('watermark', '!=', True)], 'required': [('watermark', '=', True)]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="general-right" string="General">
|
||||
<field name="pdfa"/>
|
||||
<field name="tagged_pdf" attrs="{'invisible': [('pdfa', '=', True)]}"/>
|
||||
<field name="pdf_form" attrs="{'invisible': [('pdfa', '=', True)]}"/>
|
||||
<field name="pdf_form_format" attrs="{'invisible': [('pdf_form', '!=', True)], 'required': [('pdf_form', '=', True)]}"/>
|
||||
<field name="pdf_form_allow_duplicate" attrs="{'invisible': [('pdf_form', '!=', True)]}"/>
|
||||
<field name="export_bookmarks"/>
|
||||
<field name="export_placeholders"/>
|
||||
<field name="export_comments"/>
|
||||
<field name="export_hidden_slides"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="initial_view" string="Initial View">
|
||||
<group name="initial_view">
|
||||
<group name="initial_view-left" col="1">
|
||||
<group name="panes" string="Panes">
|
||||
<field name="initial_view" widget="radio"/>
|
||||
<field name="initial_page"/>
|
||||
</group>
|
||||
<group name="magnification" string="Magnification">
|
||||
<field name="magnification" widget="radio"/>
|
||||
<field name="zoom" attrs="{'invisible': [('magnification', '!=', '4')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="initial_view-right">
|
||||
<field name="page_layout" widget="radio"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page name="user_intf" string="User Interface">
|
||||
<group name="user_intf">
|
||||
<group name="user_intf-left" col="1">
|
||||
<group name="user_intf-window-options" string="Window Options">
|
||||
<field name="resize_windows_initial_page"/>
|
||||
<field name="center_window"/>
|
||||
<field name="open_fullscreen"/>
|
||||
<field name="display_document_title"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="user_intf-right" col="1">
|
||||
<group name="user_intf-options" string="User Interface Options">
|
||||
<field name="hide_menubar"/>
|
||||
<field name="hide_toolbar"/>
|
||||
<field name="hide_window_controls"/>
|
||||
</group>
|
||||
<group string="Bookmarks" name="bookmarks">
|
||||
<field name="open_bookmark_levels"/>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Links" name="links">
|
||||
<group name="links" col="1">
|
||||
<group name="links-general" string="General">
|
||||
<field name="export_bookmarks_named_dest"/>
|
||||
<field name="convert_doc_ref_to_pdf_target"/>
|
||||
<field name="export_filesystem_urls"/>
|
||||
</group>
|
||||
<group name="links-cross-doc" string="Cross-document Links">
|
||||
<field name="cross_doc_link_action" widget="radio"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Security" name="security">
|
||||
<group name="security">
|
||||
<group name="security-left" attrs="{'invisible': [('pdfa', '=', True)]}">
|
||||
<field name="encrypt"/>
|
||||
<field name="document_password" password="True" attrs="{'invisible': [('encrypt', '!=', True)], 'required': [('encrypt', '=', True)]}"/>
|
||||
<field name="restrict_permissions"/>
|
||||
<field name="permission_password" password="True" attrs="{'invisible': [('restrict_permissions', '!=', True)], 'required': [('restrict_permissions', '=', True)]}"/>
|
||||
</group>
|
||||
<group name="security-right" attrs="{'invisible': ['|', ('pdfa', '=', True), ('restrict_permissions', '=', False)]}">
|
||||
<field name="printing" widget="radio"/>
|
||||
<field name="changes" widget="radio"/>
|
||||
<field name="content_copying_allowed"/>
|
||||
<field name="text_access_accessibility_tools_allowed"/>
|
||||
</group>
|
||||
<group name="security-pdfa" attrs="{'invisible': [('pdfa', '=', False)]}" colspan="2">
|
||||
<div><p>The security settings are incompatible with the <b>PDF/A-1a</b> option in the <em>General</em> tab.</p></div>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="py3o_pdf_options_tree" model="ir.ui.view">
|
||||
<field name="name">py3o.pdf.options.tree</field>
|
||||
<field name="model">py3o.pdf.options</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Py3o PDF Export Options">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="py3o_pdf_options_action" model="ir.actions.act_window">
|
||||
<field name="name">Py3o PDF Export Options</field>
|
||||
<field name="res_model">py3o.pdf.options</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="py3o_pdf_options_menu"
|
||||
parent="report_py3o.py3o_config_menu"
|
||||
action="py3o_pdf_options_action"
|
||||
sequence="40" />
|
||||
|
||||
|
||||
</odoo>
|
|
@ -8,6 +8,7 @@
|
|||
<form string="Py3o Server Configuration">
|
||||
<group name="main">
|
||||
<field name="url" widget="url"/>
|
||||
<field name="pdf_options_id"/>
|
||||
<field name="is_active" />
|
||||
</group>
|
||||
</form>
|
||||
|
@ -20,6 +21,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<tree string="Py3o Servers Configuration">
|
||||
<field name="url" />
|
||||
<field name="pdf_options_id"/>
|
||||
<field name="is_active" />
|
||||
</tree>
|
||||
</field>
|
||||
|
|
Loading…
Reference in New Issue