diff --git a/report_py3o_index/README.rst b/report_py3o_index/README.rst new file mode 100644 index 0000000000..afbb62f8e9 --- /dev/null +++ b/report_py3o_index/README.rst @@ -0,0 +1,91 @@ +============================================== +Py3o Report Engine: Update Indices (TOC, etc.) +============================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:527b4bd77cfdd3ff1f069091cc2701f01df1c9cbbd7ffab7ab5a207b0fc7a58d + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github + :target: https://github.com/OCA/reporting-engine/tree/16.0/report_py3o_index + :alt: OCA/reporting-engine +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/reporting-engine-16-0/reporting-engine-16-0-report_py3o_index + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module fills in the document indexes (e.g. a Table of Content) in a generated py3o document. + +This is to work around the missing feature first reported in 2012: https://bugs.documentfoundation.org/show_bug.cgi?id=44448 + +It uses the workaround given in https://ask.libreoffice.org/t/update-toc-via-command-line/52518 and other similar threads. + +Note that to work, the macro has to be installed in libreoffice first. +This is done at module install. +It assumes the macro files are stored at `~/.config/libreoffice/4/user/basic/Standard`. +If it fails, the function can be manually called with the real path using: +`self.env["py3o.report"]._install_update_index_macro(real_path)` +Make sure that this is correct as most failure paths of the macro application are silent. + +Once this is done, py3o templates have an "has index" boolean. +If set, the macro is applied after generation (and before pdf conversion) to update all indices. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Lambdao + +Contributors +~~~~~~~~~~~~ + +* Fanny He (`Lambdao `_) , +* Nans Lefebvre (`Lambdao `_) , + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/reporting-engine `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/report_py3o_index/__init__.py b/report_py3o_index/__init__.py new file mode 100644 index 0000000000..ca9b305813 --- /dev/null +++ b/report_py3o_index/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2024 fah-mili/Lambdao +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from . import models + +from .hooks import post_init_hook diff --git a/report_py3o_index/__manifest__.py b/report_py3o_index/__manifest__.py new file mode 100644 index 0000000000..61912eab0f --- /dev/null +++ b/report_py3o_index/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2024 fah-mili/Lambdao +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +{ + "name": "Py3o Report Engine: Update Indices (TOC, etc.)", + "summary": "Update indices (TOC, etc.) in Py3o reports", + "version": "16.0.1.0.0", + "category": "Reporting", + "license": "AGPL-3", + "author": "Lambdao, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/reporting-engine", + "depends": ["report_py3o"], + "data": ["views/ir_actions_report.xml", "views/py3o_template.xml"], + "installable": True, + "post_init_hook": "post_init_hook", +} diff --git a/report_py3o_index/data/ModuleUpdateIndex.xba b/report_py3o_index/data/ModuleUpdateIndex.xba new file mode 100644 index 0000000000..8f22be2f6a --- /dev/null +++ b/report_py3o_index/data/ModuleUpdateIndex.xba @@ -0,0 +1,28 @@ + + +REM ***** BASIC ***** + + Option Explicit + + Sub UpdateIndexes(path As String) + '''Update indexes, such as for the table of contents''' + Dim doc As Object + Dim args() + + doc = StarDesktop.loadComponentFromUrl(convertToUrl(path), "_default", 0, args()) + + Dim i As Integer + + With doc ' Only process Writer documents + If .supportsService("com.sun.star.text.GenericTextDocument") Then + For i = 0 To .getDocumentIndexes().count - 1 + .getDocumentIndexes().getByIndex(i).update() + Next i + End If + End With ' ThisComponent + + doc.store() + doc.close(True) + + End Sub ' UpdateIndexes + diff --git a/report_py3o_index/hooks.py b/report_py3o_index/hooks.py new file mode 100644 index 0000000000..3d617daf21 --- /dev/null +++ b/report_py3o_index/hooks.py @@ -0,0 +1,20 @@ +# Copyright 2024 fah-mili/Lambdao +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import SUPERUSER_ID, api + +_logger = logging.getLogger(__name__) + + +def post_init_hook(cr, registry): + _logger.info("Install index update macro with default path.") + env = api.Environment(cr, SUPERUSER_ID, {}) + try: + env["py3o.report"]._install_update_index_macro() + except Exception as e: + _logger.warn("Failed to install index update macro.") + _logger.warn("--------") + _logger.warn(e) + _logger.warn("--------") diff --git a/report_py3o_index/models/__init__.py b/report_py3o_index/models/__init__.py new file mode 100644 index 0000000000..7d8fdab53a --- /dev/null +++ b/report_py3o_index/models/__init__.py @@ -0,0 +1,7 @@ +# Copyright 2024 fah-mili/Lambdao +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from . import py3o_template +from . import ir_actions_report +from . import py3o_report diff --git a/report_py3o_index/models/ir_actions_report.py b/report_py3o_index/models/ir_actions_report.py new file mode 100644 index 0000000000..da65608511 --- /dev/null +++ b/report_py3o_index/models/ir_actions_report.py @@ -0,0 +1,16 @@ +# Copyright 2024 fah-mili/Lambdao +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from odoo import fields, models + + +class IrActionsReport(models.Model): + + _inherit = "ir.actions.report" + py3o_has_index_fallback = fields.Boolean( + "Has Py3o Index? (Fallback)", + default=False, + help="Check if the template fallback has a py3o index. " + "It needs to be compiled twice to get the index right.", + ) diff --git a/report_py3o_index/models/py3o_report.py b/report_py3o_index/models/py3o_report.py new file mode 100644 index 0000000000..4f7a4bba62 --- /dev/null +++ b/report_py3o_index/models/py3o_report.py @@ -0,0 +1,90 @@ +# Copyright 2024 fah-mili/Lambdao +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +import logging +import os +import subprocess + +import pkg_resources + +from odoo import api, fields, models + +logger = logging.getLogger(__name__) + + +class Py3oReport(models.TransientModel): + _inherit = "py3o.report" + + py3o_has_index = fields.Boolean( + "Has Py3o Index?", + default=False, + compute="_compute_py3o_has_index", + help="Check if the template has a py3o index. " + "It needs to be compiled twice to get the index right.", + ) + + @api.depends( + "ir_actions_report_id.py3o_template_id.py3o_has_index", + "ir_actions_report_id.py3o_has_index_fallback", + ) + def _compute_py3o_has_index(self): + for rec in self: + if rec.ir_actions_report_id.py3o_template_id: + value = rec.ir_actions_report_id.py3o_template_id.py3o_has_index + else: + value = rec.ir_actions_report_id.py3o_has_index_fallback + rec.py3o_has_index = value + + @api.model + def _install_update_index_macro(self, path=None): + """Install or update the py3o index macro""" + # the real path is an argument so that in case it fails it can be + # called again with the correct one; after that it's LO's internal + # macro naming that will be used + # we could also have a parameter for the macro name but + # is it worth the complexity? + if not path: + path = "~/.config/libreoffice/4/user/basic/Standard" + real_path = os.path.realpath(os.path.expanduser(path)) + file_macro = "ModuleUpdateIndex.xba" + macro_path = os.path.join(real_path, file_macro) + if not os.path.exists(macro_path): + # copy the new macro to libreoffice macro folder + content_path = pkg_resources.resource_filename( + "odoo.addons.report_py3o_index", "data/ModuleUpdateIndex.xba" + ) + with open(content_path, "r") as f: + content = f.read() + with open(macro_path, "w") as f: + f.write(content) + file_script = "script.xlb" + script_path = os.path.join(real_path, file_script) + mac = '' + with open(script_path, "r") as f: + script_content = f.read() + if mac not in script_content: + end_marker = "" + marker_line = mac + "\n" + end_marker + new_content = script_content.replace(end_marker, marker_line) + with open(script_path, "w") as f: + f.write(new_content) + + def _convert_single_report(self, result_path, model_instance, data): + # this needs to be done before the report is converted to pdf! + # data is an unused dict, the file is obtained from the result_path + if self.py3o_has_index: + self._update_index(result_path) + result = super(Py3oReport, self)._convert_single_report( + result_path, model_instance, data + ) + return result + + def _update_index(self, result_path): + """Run a command to update the index""" + path = "macro:///Standard.ModuleUpdateIndex.UpdateIndexes(%s)" % result_path + lo_bin = self.ir_actions_report_id.lo_bin_path + cmd = [lo_bin, "--headless", path] + # if something goes wrong, it's not giving any error message... + subprocess.check_output(cmd, cwd=os.path.dirname(result_path)) + return result_path diff --git a/report_py3o_index/models/py3o_template.py b/report_py3o_index/models/py3o_template.py new file mode 100644 index 0000000000..6dff248211 --- /dev/null +++ b/report_py3o_index/models/py3o_template.py @@ -0,0 +1,16 @@ +# Copyright 2024 fah-mili/Lambdao +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + + +from odoo import fields, models + + +class Py3oTemplate(models.Model): + _inherit = "py3o.template" + + py3o_has_index = fields.Boolean( + "Has Py3o Index?", + default=False, + help="Check if the template has a py3o index. " + "It needs to be compiled twice to get the index right.", + ) diff --git a/report_py3o_index/readme/CONTRIBUTORS.rst b/report_py3o_index/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..db83247dba --- /dev/null +++ b/report_py3o_index/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Fanny He (`Lambdao `_) , +* Nans Lefebvre (`Lambdao `_) , diff --git a/report_py3o_index/readme/DESCRIPTION.rst b/report_py3o_index/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..3a0cea0296 --- /dev/null +++ b/report_py3o_index/readme/DESCRIPTION.rst @@ -0,0 +1,15 @@ +This module fills in the document indexes (e.g. a Table of Content) in a generated py3o document. + +This is to work around the missing feature first reported in 2012: https://bugs.documentfoundation.org/show_bug.cgi?id=44448 + +It uses the workaround given in https://ask.libreoffice.org/t/update-toc-via-command-line/52518 and other similar threads. + +Note that to work, the macro has to be installed in libreoffice first. +This is done at module install. +It assumes the macro files are stored at `~/.config/libreoffice/4/user/basic/Standard`. +If it fails, the function can be manually called with the real path using: +`self.env["py3o.report"]._install_update_index_macro(real_path)` +Make sure that this is correct as most failure paths of the macro application are silent. + +Once this is done, py3o templates have an "has index" boolean. +If set, the macro is applied after generation (and before pdf conversion) to update all indices. diff --git a/report_py3o_index/static/description/icon.png b/report_py3o_index/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/report_py3o_index/static/description/icon.png differ diff --git a/report_py3o_index/static/description/index.html b/report_py3o_index/static/description/index.html new file mode 100644 index 0000000000..41f592acc8 --- /dev/null +++ b/report_py3o_index/static/description/index.html @@ -0,0 +1,434 @@ + + + + + +Py3o Report Engine: Update Indices (TOC, etc.) + + + +
+

Py3o Report Engine: Update Indices (TOC, etc.)

+ + +

Beta License: AGPL-3 OCA/reporting-engine Translate me on Weblate Try me on Runboat

+

This module fills in the document indexes (e.g. a Table of Content) in a generated py3o document.

+

This is to work around the missing feature first reported in 2012: https://bugs.documentfoundation.org/show_bug.cgi?id=44448

+

It uses the workaround given in https://ask.libreoffice.org/t/update-toc-via-command-line/52518 and other similar threads.

+

Note that to work, the macro has to be installed in libreoffice first. +This is done at module install. +It assumes the macro files are stored at ~/.config/libreoffice/4/user/basic/Standard. +If it fails, the function can be manually called with the real path using: +self.env[“py3o.report”]._install_update_index_macro(real_path) +Make sure that this is correct as most failure paths of the macro application are silent.

+

Once this is done, py3o templates have an “has index” boolean. +If set, the macro is applied after generation (and before pdf conversion) to update all indices.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Lambdao
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/reporting-engine project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/report_py3o_index/views/ir_actions_report.xml b/report_py3o_index/views/ir_actions_report.xml new file mode 100644 index 0000000000..2ca2e9334c --- /dev/null +++ b/report_py3o_index/views/ir_actions_report.xml @@ -0,0 +1,30 @@ + + + + + py3o_report_view + ir.actions.report + + + + + + + + + + py3o_report_search_view_py3o_index + ir.actions.report + + + + + + + + diff --git a/report_py3o_index/views/py3o_template.xml b/report_py3o_index/views/py3o_template.xml new file mode 100644 index 0000000000..8eba7ffb51 --- /dev/null +++ b/report_py3o_index/views/py3o_template.xml @@ -0,0 +1,55 @@ + + + + + py3o.template.configuration.search.view.index + py3o.template + + + + + + + + + + + py3o.template.configuration.form.view.index + py3o.template + + + + + + + + + + py3o.template.configuration.tree.view + py3o.template + + + + + + + + diff --git a/setup/report_py3o_index/odoo/addons/report_py3o_index b/setup/report_py3o_index/odoo/addons/report_py3o_index new file mode 120000 index 0000000000..19848a3f28 --- /dev/null +++ b/setup/report_py3o_index/odoo/addons/report_py3o_index @@ -0,0 +1 @@ +../../../../report_py3o_index \ No newline at end of file diff --git a/setup/report_py3o_index/setup.py b/setup/report_py3o_index/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/report_py3o_index/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)