#!/usr/bin/env python3 # ~ This file is part of ZAZ. # ~ ZAZ is free software: you can redistribute it and/or modify # ~ it under the terms of the GNU General Public License as published by # ~ the Free Software Foundation, either version 3 of the License, or # ~ (at your option) any later version. # ~ ZAZ is distributed in the hope that it will be useful, # ~ but WITHOUT ANY WARRANTY; without even the implied warranty of # ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # ~ GNU General Public License for more details. # ~ You should have received a copy of the GNU General Public License # ~ along with ZAZ. If not, see . import logging # ~ Type extension: # ~ 1 = normal extension # ~ 2 = new component # ~ 3 = Calc addin TYPE_EXTENSION = 1 # ~ https://semver.org/ VERSION = '1.0.0' # ~ Your great extension name, not used spaces NAME = 'ZAZPip' # ~ Should be unique, used URL inverse ID = 'net.elmau.zaz.pip' # ~ If you extension will be multilanguage set: True # ~ This feature used gettext, set pythonpath and easymacro in True # ~ You can used PoEdit for edit PO files and generate MO files. # ~ https://poedit.net/ USE_LOCALES = True DOMAIN = 'base' PATH_LOCALES = 'locales' PATH_PYGETTEXT = '/usr/lib/python3.10/Tools/i18n/pygettext.py' PATH_MSGMERGE = 'msgmerge' # ~ Show in extension manager URL_GIT = 'https://git.cuates.net/elmau/zaz-pip' PUBLISHER = { 'en': {'text': 'El Mau', 'link': URL_GIT}, 'es': {'text': 'El Mau', 'link': URL_GIT}, 'fr': {'text': 'El Mau', 'link': URL_GIT}, } # ~ Name in this folder for copy ICON = 'images/logo.png' # ~ Name inside extensions ICON_EXT = f'{NAME.lower()}.png' DEPENDENCIES_MINIMAL = '7.0' # ~ Change for you favorite license LICENSE_EN = f"""This file is part of {NAME}. {NAME} is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. {NAME} is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with {NAME}. If not, see . """ LICENSE_FR = LICENSE_ES = LICENSE_EN INFO = { 'en': { 'display_name': 'ZAZ Pip', 'description': 'Pip for LibreOffice', 'license': LICENSE_EN, }, 'es': { 'display_name': 'ZAZ Pip', 'description': 'Pip para LibreOffice', 'license': LICENSE_ES, }, 'fr': { 'display_name': 'ZAZ Pip', 'description': 'Pip pour LibreOffice', 'license': LICENSE_FR, }, } # ~ Menus, only for TYPE_EXTENSION = 1 # ~ Parent can be: AddonMenu or OfficeMenuBar # ~ For icons con name: NAME_16.bmp, used only NAME # ~ PARENT = '' # ~ MENU_MAIN = {} # ~ Shortcut: Key + "Modifier Keys" # ~ Important: Not used any shortcuts used for LibreOffice # ~ SHIFT is mapped to Shift on all platforms. # ~ MOD1 is mapped to Ctrl on Windows/Linux, while it is mapped to Cmd on Mac. # ~ MOD2 is mapped to Alt on all platforms. # ~ For example: Shift+Ctrl+Alt+T -> T_SHIFT_MOD1_MOD2 PARENT = 'AddonMenu' # ~ MENU_MAIN = { # ~ 'en': 'My Extension', # ~ 'es': 'Mi Extensión', # ~ } MENU_MAIN = {} MENUS = ( { 'title': {'en': 'Open Zaz-Pip', 'es': 'Abrir Zaz-Pip', 'fr': 'Ouvert Zaz-Pip'}, 'argument': 'open_dialog_pip', 'context': '', 'icon': 'icon', 'toolbar': False, 'shortcut': 'P_SHIFT_MOD1_MOD2', }, ) # ~ Functions, only for TYPE_EXTENSION = 3 FUNCTIONS = { 'test': { 'displayname': {'en': 'test', 'es': 'prueba'}, 'description': {'en': 'My test', 'es': 'Mi prueba'}, 'parameters': { 'value': { 'displayname': {'en': 'value', 'es': 'valor'}, 'description': {'en': 'The value', 'es': 'El valor'}, }, }, }, } # ~ FUNCTIONS = {} EXTENSION = { 'version': VERSION, 'name': NAME, 'id': ID, 'icon': (ICON, ICON_EXT), 'languages': tuple(INFO.keys()) } # ~ If used more libraries set python path in True and copy inside # ~ If used easymacro pythonpath always is True, recommended DIRS = { 'meta': 'META-INF', 'source': 'source', 'description': 'description', 'images': 'images', 'registration': 'registration', 'files': 'extension', 'office': 'Office', 'locales': PATH_LOCALES, 'pythonpath': True, } FILES = { 'oxt': f'{NAME}_v{VERSION}.oxt', 'py': f'{NAME}.py', 'ext_desc': 'desc_{}.txt', 'manifest': 'manifest.xml', 'description': 'description.xml', 'idl': f'X{NAME}.idl', 'addons': 'Addons.xcu', 'urd': f'X{NAME}.urd', 'rdb': f'X{NAME}.rdb', 'update': f'{NAME.lower()}.update.xml', 'addin': 'CalcAddIn.xcu', 'shortcut': 'Accelerators.xcu', 'easymacro': True, } # ~ URLs for update for example # ~ URL_XML_UPDATE = 'https://gitlab.com/USER/PROYECT/raw/BRANCH/FOLDERs/FILE_NAME' URL_XML_UPDATE = '' URL_OXT = '' # ~ Default program for test: --calc, --writer, --draw PROGRAM = '--calc' # ~ Path to file for test FILE_TEST = '' PATHS = { 'idlc': '/usr/lib/libreoffice/sdk/bin/idlc', 'include': '/usr/share/idl/libreoffice', 'regmerge': '/usr/lib/libreoffice/program/regmerge', 'soffice': ('soffice', PROGRAM, FILE_TEST), 'install': ('unopkg', 'add', '-v', '-f', '-s'), 'profile': '/home/mau/.config/libreoffice/4/user', 'gettext': PATH_PYGETTEXT, 'msgmerge': PATH_MSGMERGE, } SERVICES = { 'job': "('com.sun.star.task.Job',)", 'addin': "('com.sun.star.sheet.AddIn',)", } FORMAT = '%(asctime)s - %(levelname)s - %(message)s' DATE = '%d/%m/%Y %H:%M:%S' LEVEL_ERROR = logging.getLevelName(logging.ERROR) LEVEL_INFO = logging.getLevelName(logging.INFO) logging.addLevelName(logging.ERROR, f'\033[1;41m{LEVEL_ERROR}\033[1;0m') logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m') logging.basicConfig(level=logging.DEBUG, format=FORMAT, datefmt=DATE) log = logging.getLogger(NAME) def _methods(): template = """ def {0}(self, {1}): print({1}) return 'ok'\n""" functions = '' for k, v in FUNCTIONS.items(): args = ','.join(v['parameters'].keys()) functions += template.format(k, args) return functions SRV = SERVICES['job'] XSRV = 'XJobExecutor' SRV_IMPORT = f'from com.sun.star.task import {XSRV}' METHODS = """ def trigger(self, args='pyUNO'): print('Hello World', args) return\n""" if TYPE_EXTENSION > 1: MENUS = () XSRV = f'X{NAME}' SRV_IMPORT = f'from {ID} import {XSRV}' if TYPE_EXTENSION == 2: SRV = f"('{ID}',)" METHODS = """ def test(self, args='pyUNO'): print('Hello World', args) return\n""" elif TYPE_EXTENSION == 3: SRV = SERVICES['addin'] METHODS = _methods() DATA_PY = f"""import uno import unohelper {SRV_IMPORT} ID_EXTENSION = '{ID}' SERVICE = {SRV} class {NAME}(unohelper.Base, {XSRV}): def __init__(self, ctx): self.ctx = ctx {METHODS} g_ImplementationHelper = unohelper.ImplementationHelper() g_ImplementationHelper.addImplementation({NAME}, ID_EXTENSION, SERVICE) """ def _functions(): a = '[in] any {}' t = ' any {}({});' f = '' for k, v in FUNCTIONS.items(): args = ','.join([a.format(k) for k, v in v['parameters'].items()]) f += t.format(k, args) return f FILE_IDL = '' if TYPE_EXTENSION > 1: id_ext = ID.replace('.', '_') interface = f'X{NAME}' module = '' for i, P in enumerate(ID.split('.')): module += f'module {P} {{ ' close_module = '}; ' * (i + 1) functions = ' void test([in] any argument);' if TYPE_EXTENSION == 3: functions = _functions() FILE_IDL = f"""#ifndef __{id_ext}_idl__ #define __{id_ext}_idl__ #include {module} interface {interface} : com::sun::star::uno::XInterface {{ {functions} }}; service {P} {{ interface {interface}; }}; {close_module} #endif """ def _parameters(args): NODE = """ {displayname} {description} """ line = '{}{}' node = '' for k, v in args.items(): displayname = '\n'.join( [line.format(' ' * 16, k, v) for k, v in v['displayname'].items()]) description = '\n'.join( [line.format(' ' * 16, k, v) for k, v in v['description'].items()]) values = { 'name': k, 'displayname': displayname, 'description': description, } node += NODE.format(**values) return node NODE_FUNCTIONS = '' if TYPE_EXTENSION == 3: tmp = '{}{}' NODE_FUNCTION = """ {displayname} {description} Add-In AutoAddIn.{name} {parameters} """ for k, v in FUNCTIONS.items(): displayname = '\n'.join( [tmp.format(' ' * 12, k, v) for k, v in v['displayname'].items()]) description = '\n'.join( [tmp.format(' ' * 12, k, v) for k, v in v['description'].items()]) parameters = _parameters(v['parameters']) values = { 'name': k, 'displayname': displayname, 'description': description, 'parameters': parameters, } NODE_FUNCTIONS += NODE_FUNCTION.format(**values) FILE_ADDIN = f""" {NODE_FUNCTIONS} """ DATA_MANIFEST = [FILES['py'], f"Office/{FILES['shortcut']}", 'Addons.xcu'] if TYPE_EXTENSION > 1: DATA_MANIFEST.append(FILES['rdb']) if TYPE_EXTENSION == 3: DATA_MANIFEST.append('CalcAddIn.xcu') DATA_DESCRIPTION = { 'identifier': {'value': ID}, 'version': {'value': VERSION}, 'display-name': {k: v['display_name'] for k, v in INFO.items()}, 'icon': ICON_EXT, 'publisher': PUBLISHER, 'update': URL_XML_UPDATE, 'minimal': DEPENDENCIES_MINIMAL, } DATA_ADDONS = { 'parent': PARENT, 'images': DIRS['images'], 'main': MENU_MAIN, 'menus': MENUS, } DATA = { 'py': DATA_PY, 'manifest': DATA_MANIFEST, 'description': DATA_DESCRIPTION, 'addons': DATA_ADDONS, 'update': URL_OXT, 'idl': FILE_IDL, 'addin': FILE_ADDIN, } with open('VERSION', 'w') as f: f.write(VERSION) # ~ LICENSE_ACCEPT_BY = 'user' # or admin # ~ LICENSE_SUPPRESS_ON_UPDATE = True