Init version
This commit is contained in:
parent
930a55709c
commit
fc81ceddb0
|
@ -0,0 +1,14 @@
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
|
||||||
|
*.log
|
||||||
|
conf.py
|
||||||
|
files/
|
||||||
|
|
||||||
|
docs/
|
||||||
|
|
||||||
|
# Virtualenv
|
||||||
|
.env/
|
||||||
|
virtual/
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
v 0.1.0 [06-sep-2019]
|
||||||
|
---------------------
|
||||||
|
- Initial version
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
* Used zaz and easymacro
|
||||||
|
* Report errors
|
||||||
|
* Add examples
|
||||||
|
* Add to list of proyects develop with zaz or easymacro
|
||||||
|
* Send me a postal card
|
||||||
|
* Pay for support
|
||||||
|
|
||||||
|
|
||||||
|
**BCH**: `pzkuydh70v4r52hl3nqs66gy9wqdtrgej5ewv48xyq`
|
||||||
|
|
||||||
|
**BTC**: `3FhiXcXmAesmQzrNEngjHFnvaJRhU1AGWV`
|
||||||
|
|
||||||
|
**LTC**: `MBcgQ3LQJA4W2wsXknTdm2fxRSysLaBJHS`
|
||||||
|
|
||||||
|
**ETH**: `0x61a4f614a30ff686445751ed8328b82b77ecfc69`
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
ZAZ
|
ZAZ
|
||||||
|
|
||||||
Scripts and library for develop macros in LibreOffice with Python.
|
Scripts and library for develop macros in LibreOffice with Python.
|
||||||
|
|
||||||
|
Develop in pure Python, not need any dependence.
|
||||||
|
|
||||||
|
For Python 3.6+
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
* Automatic update
|
||||||
|
* Help
|
||||||
|
* Configuration
|
||||||
|
* Option panel
|
||||||
|
* Sub-menus
|
|
@ -0,0 +1,541 @@
|
||||||
|
# ~ 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
# ~ Type extension:
|
||||||
|
# ~ 1 = normal extension
|
||||||
|
# ~ 2 = new component
|
||||||
|
# ~ 3 = Calc addin
|
||||||
|
TYPE_EXTENSION = 1
|
||||||
|
|
||||||
|
# ~ https://semver.org/
|
||||||
|
VERSION = '0.1.0'
|
||||||
|
|
||||||
|
# ~ Your great extension name, not used spaces
|
||||||
|
NAME = 'TestMacro'
|
||||||
|
|
||||||
|
# ~ Should be unique, used URL inverse
|
||||||
|
ID = 'org.myextension.test'
|
||||||
|
|
||||||
|
PUBLISHER = {
|
||||||
|
'en': {'text': 'El Mau', 'link': 'https://elmau.net'},
|
||||||
|
'es': {'text': 'El Mau', 'link': 'https://elmau.net'},
|
||||||
|
}
|
||||||
|
|
||||||
|
# ~ Name in this folder for copy
|
||||||
|
ICON = 'images/logo.png'
|
||||||
|
# ~ Name inside extensions
|
||||||
|
ICON_EXT = f'{NAME.lower()}.png'
|
||||||
|
|
||||||
|
# ~ For example
|
||||||
|
# ~ DEPENDENCIES_MINIMAL = '6.0'
|
||||||
|
DEPENDENCIES_MINIMAL = ''
|
||||||
|
|
||||||
|
LICENSE_ACCEPT_BY = 'user' # or admin
|
||||||
|
LICENSE_SUPPRESS_ON_UPDATE = True
|
||||||
|
# ~ 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 <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
LICENSE_ES = LICENSE_EN
|
||||||
|
|
||||||
|
INFO = {
|
||||||
|
'en': {
|
||||||
|
'display_name': 'Test Macro',
|
||||||
|
'description': 'My great extension',
|
||||||
|
'license': LICENSE_EN,
|
||||||
|
},
|
||||||
|
'es': {
|
||||||
|
'display_name': 'Macro de Prueba',
|
||||||
|
'description': 'Mi gran extensión',
|
||||||
|
'license': LICENSE_ES,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CONTEXT = {
|
||||||
|
'calc': 'com.sun.star.sheet.SpreadsheetDocument',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ~ Menus, only for TYPE_EXTENSION = 1
|
||||||
|
# ~ Parent can be: AddonMenu or OfficeMenuBar
|
||||||
|
# ~ For icons con name: NAME_16.bmp, used only NAME
|
||||||
|
# ~ PARENT = 'AddonMenu'
|
||||||
|
# ~ MENU_MAIN = ''
|
||||||
|
PARENT = 'OfficeMenuBar'
|
||||||
|
MENU_MAIN = {
|
||||||
|
'en': 'My Extension',
|
||||||
|
'es': 'Mi Extensión',
|
||||||
|
}
|
||||||
|
MENUS = (
|
||||||
|
{
|
||||||
|
'title': {'en': 'Option 1', 'es': 'Opción 1'},
|
||||||
|
'argument': 'option1',
|
||||||
|
'context': '',
|
||||||
|
'icon': 'icon',
|
||||||
|
'toolbar': True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# ~ 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),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# If used more libraries set python path in True and copy inside
|
||||||
|
DIRS = {
|
||||||
|
'meta': 'META-INF',
|
||||||
|
'source': 'source',
|
||||||
|
'description': 'description',
|
||||||
|
'images': 'images',
|
||||||
|
'registration': 'registration',
|
||||||
|
'files': 'files',
|
||||||
|
'pythonpath': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ~ URLs for update for example
|
||||||
|
# ~ URL_XML_UPDATE = 'https://gitlab.com/USER/PROYECT/raw/BRANCH/FOLDERs/FILE_NAME'
|
||||||
|
URL_XML_UPDATE = ''
|
||||||
|
URL_OXT = ''
|
||||||
|
|
||||||
|
|
||||||
|
# ~ If used user profile for develop
|
||||||
|
# ~ PATH_DEV = '-env:UserInstallation=file:///home/mau/.temp/develop'
|
||||||
|
# ~ unopkg not support (or I not know how) other user profile
|
||||||
|
PATH_DEV = ''
|
||||||
|
PATHS = {
|
||||||
|
'idlc': '/usr/lib/libreoffice/sdk/bin/idlc',
|
||||||
|
'include': '/usr/share/idl/libreoffice',
|
||||||
|
'regmerge': '/usr/lib/libreoffice/program/regmerge',
|
||||||
|
'soffice': ('soffice', '--calc'),
|
||||||
|
'install': ('unopkg', 'add', '-v', '-f', '-s'),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
FILE_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)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
tmp = ' <name lang="{}">{}</name>'
|
||||||
|
node = [tmp.format(k, v['display_name']) for k, v in INFO.items()]
|
||||||
|
NODE_DISPLAY_NAME = '\n'.join(node)
|
||||||
|
|
||||||
|
tmp = ' <src lang="{0}" xlink:href="description/desc_{0}.txt" />'
|
||||||
|
node = [tmp.format(k) for k, v in INFO.items()]
|
||||||
|
NODE_EXTENSION_DESCRIPTION = '\n'.join(node)
|
||||||
|
|
||||||
|
NODE_ICON = ''
|
||||||
|
if ICON:
|
||||||
|
NODE_ICON = f' <default xlink:href="images/{ICON_EXT}" />'
|
||||||
|
|
||||||
|
NODE_PUBLISHER = ''
|
||||||
|
if PUBLISHER:
|
||||||
|
tmp = ' <name xlink:href="{}" lang="{}">{}</name>'
|
||||||
|
node = [tmp.format(v['link'], k, v['text']) for k, v in PUBLISHER.items()]
|
||||||
|
NODE_PUBLISHER = '\n'.join(node)
|
||||||
|
|
||||||
|
NODE_DEPENDENCIES_MINIMAL = ''
|
||||||
|
if DEPENDENCIES_MINIMAL:
|
||||||
|
NODE_DEPENDENCIES_MINIMAL = f"""\n <dependencies>
|
||||||
|
<OpenOffice.org-minimal-version value="{DEPENDENCIES_MINIMAL}" d:name="LibreOffice {DEPENDENCIES_MINIMAL}"/>
|
||||||
|
</dependencies>"""
|
||||||
|
|
||||||
|
tmp = ' <license-text xlink:href="{0}/license_{1}.txt" lang="{1}" />'
|
||||||
|
node = [tmp.format(DIRS['registration'], k) for k in INFO.keys()]
|
||||||
|
NODE_LICENSE = '\n'.join(node)
|
||||||
|
|
||||||
|
NODE_UPDATE = ''
|
||||||
|
if URL_XML_UPDATE:
|
||||||
|
NODE_UPDATE = f"""
|
||||||
|
<update-information>
|
||||||
|
<src xlink:href="{URL_XML_UPDATE}" />
|
||||||
|
</update-information>"""
|
||||||
|
|
||||||
|
FILE_DESCRIPTION = f"""<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:d="http://openoffice.org/extensions/description/2006">
|
||||||
|
<identifier value="{ID}" />
|
||||||
|
<version value="{VERSION}" />
|
||||||
|
<display-name>
|
||||||
|
{NODE_DISPLAY_NAME}
|
||||||
|
</display-name>
|
||||||
|
<extension-description>
|
||||||
|
{NODE_EXTENSION_DESCRIPTION}
|
||||||
|
</extension-description>
|
||||||
|
<icon>
|
||||||
|
{NODE_ICON}
|
||||||
|
</icon>
|
||||||
|
<publisher>
|
||||||
|
{NODE_PUBLISHER}
|
||||||
|
</publisher>
|
||||||
|
<registration>
|
||||||
|
<simple-license accept-by="{LICENSE_ACCEPT_BY}" suppress-on-update="{LICENSE_SUPPRESS_ON_UPDATE}" >
|
||||||
|
{NODE_LICENSE}
|
||||||
|
</simple-license>
|
||||||
|
</registration>{NODE_DEPENDENCIES_MINIMAL}{NODE_UPDATE}
|
||||||
|
</description>
|
||||||
|
"""
|
||||||
|
|
||||||
|
NODE_MENU = """ <node oor:name="{id}.{index}" oor:op="{opt}">
|
||||||
|
<prop oor:name="Title" oor:type="xs:string">
|
||||||
|
{titles}
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="URL" oor:type="xs:string">
|
||||||
|
<value>service:{id}?{argument}</value>
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="Target" oor:type="xs:string">
|
||||||
|
<value>_self</value>
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="Context" oor:type="xs:string">
|
||||||
|
<value>{context}</value>
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="ImageIdentifier" oor:type="xs:string">
|
||||||
|
<value>%origin%/{folder}/{icon}</value>
|
||||||
|
</prop>
|
||||||
|
</node>"""
|
||||||
|
|
||||||
|
opt = 'fuse'
|
||||||
|
if PARENT == 'OfficeMenuBar':
|
||||||
|
opt = 'replace'
|
||||||
|
|
||||||
|
menus = []
|
||||||
|
toolbar = []
|
||||||
|
tmp = ' <value xml:lang="{}">{}</value>'
|
||||||
|
for i, m in enumerate(MENUS):
|
||||||
|
titles = [tmp.format(k, v) for k, v in m['title'].items()]
|
||||||
|
values = {
|
||||||
|
'id': ID,
|
||||||
|
'index': i+101,
|
||||||
|
'opt': opt,
|
||||||
|
'titles': '\n'.join(titles),
|
||||||
|
'argument': m['argument'],
|
||||||
|
'context': m['context'],
|
||||||
|
'folder': DIRS['images'],
|
||||||
|
'icon': m['icon'],
|
||||||
|
}
|
||||||
|
menus.append(NODE_MENU.format(**values))
|
||||||
|
if m['toolbar']:
|
||||||
|
values['index'] = f't{i+1}'
|
||||||
|
toolbar.append(NODE_MENU.format(**values))
|
||||||
|
|
||||||
|
NODE_TOOLBAR = ''
|
||||||
|
if PARENT == 'AddonMenu':
|
||||||
|
NODE_MENUS = '\n'.join(menus)
|
||||||
|
else:
|
||||||
|
tmp = ' <value xml:lang="{}">{}</value>'
|
||||||
|
titles = '\n'.join([tmp.format(k, v) for k, v in MENU_MAIN.items()])
|
||||||
|
SUBMENUS = '<node oor:name="Submenu">\n ' + '\n'.join(menus) + '\n </node>'
|
||||||
|
NODE_MENUS = f""" <node oor:name="{ID}" oor:op="replace">
|
||||||
|
<prop oor:name="Title" oor:type="xs:string">
|
||||||
|
{titles}
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="Target" oor:type="xs:string">
|
||||||
|
<value>_self</value>
|
||||||
|
</prop>
|
||||||
|
{SUBMENUS}
|
||||||
|
</node>"""
|
||||||
|
|
||||||
|
if toolbar:
|
||||||
|
node_toolbars = '\n'.join(toolbar)
|
||||||
|
NODE_TOOLBAR = f""" <node oor:name="OfficeToolBar">
|
||||||
|
<node oor:name="{ID}" oor:op="replace">
|
||||||
|
{node_toolbars}
|
||||||
|
</node>
|
||||||
|
</node>"""
|
||||||
|
|
||||||
|
FILE_ADDONS = f"""<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Addons" oor:package="org.openoffice.Office">
|
||||||
|
<node oor:name="AddonUI">
|
||||||
|
<node oor:name="{PARENT}">
|
||||||
|
{NODE_MENUS}
|
||||||
|
</node>
|
||||||
|
{NODE_TOOLBAR}
|
||||||
|
</node>
|
||||||
|
</oor:component-data>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
NODE_ADDONS = '\n <manifest:file-entry manifest:full-path="Addons.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>'
|
||||||
|
if TYPE_EXTENSION > 1:
|
||||||
|
NODE_ADDONS = f'\n <manifest:file-entry manifest:full-path="{FILES["rdb"]}" manifest:media-type="application/vnd.sun.star.uno-typelibrary;type=RDB"/>'
|
||||||
|
if TYPE_EXTENSION == 3:
|
||||||
|
NODE_ADDONS += '\n <manifest:file-entry manifest:full-path="CalcAddIn.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>'
|
||||||
|
|
||||||
|
FILE_MANIFEST = f"""<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<manifest:manifest>
|
||||||
|
<manifest:file-entry manifest:full-path="{FILES['py']}" manifest:media-type="application/vnd.sun.star.uno-component;type=Python"/>{NODE_ADDONS}
|
||||||
|
</manifest:manifest>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
FILE_UPDATE = ''
|
||||||
|
if URL_XML_UPDATE:
|
||||||
|
FILE_UPDATE = f"""<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<description
|
||||||
|
xmlns="http://openoffice.org/extensions/update/2006"
|
||||||
|
xmlns:d="http://openoffice.org/extensions/description/2006"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
|
||||||
|
<identifier value="{ID}" />
|
||||||
|
<version value="{VERSION}" />
|
||||||
|
|
||||||
|
<update-download>
|
||||||
|
<src xlink:href="{URL_OXT}"/>
|
||||||
|
</update-download>
|
||||||
|
<release-notes>
|
||||||
|
</release-notes>
|
||||||
|
|
||||||
|
</description>"""
|
||||||
|
|
||||||
|
|
||||||
|
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 <com/sun/star/uno/XInterface.idl>
|
||||||
|
|
||||||
|
{module}
|
||||||
|
|
||||||
|
interface {interface} : com::sun::star::uno::XInterface
|
||||||
|
{{
|
||||||
|
{functions}
|
||||||
|
}};
|
||||||
|
|
||||||
|
service {P} {{
|
||||||
|
interface {interface};
|
||||||
|
}};
|
||||||
|
|
||||||
|
{close_module}
|
||||||
|
#endif
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _parameters(args):
|
||||||
|
NODE = """ <node oor:name="{name}" oor:op="replace">
|
||||||
|
<prop oor:name="DisplayName">
|
||||||
|
{displayname}
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="Description">
|
||||||
|
{description}
|
||||||
|
</prop>
|
||||||
|
</node>"""
|
||||||
|
line = '{}<value xml:lang="{}">{}</value>'
|
||||||
|
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 = '{}<value xml:lang="{}">{}</value>'
|
||||||
|
NODE_FUNCTION = """ <node oor:name="{name}" oor:op="replace">
|
||||||
|
<prop oor:name="DisplayName">
|
||||||
|
{displayname}
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="Description">
|
||||||
|
{description}
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="Category">
|
||||||
|
<value>Add-In</value>
|
||||||
|
</prop>
|
||||||
|
<prop oor:name="CompatibilityName">
|
||||||
|
<value xml:lang="en">AutoAddIn.{name}</value>
|
||||||
|
</prop>
|
||||||
|
<node oor:name="Parameters">
|
||||||
|
{parameters}
|
||||||
|
</node>
|
||||||
|
</node>"""
|
||||||
|
|
||||||
|
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"""<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="CalcAddIns" oor:package="org.openoffice.Office">
|
||||||
|
<node oor:name="AddInInfo">
|
||||||
|
<node oor:name="{ID}" oor:op="replace">
|
||||||
|
<node oor:name="AddInFunctions">
|
||||||
|
{NODE_FUNCTIONS}
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
</oor:component-data>"""
|
||||||
|
|
||||||
|
|
||||||
|
DATA = {
|
||||||
|
'py': FILE_PY,
|
||||||
|
'manifest': FILE_MANIFEST,
|
||||||
|
'description': FILE_DESCRIPTION,
|
||||||
|
'addons': FILE_ADDONS,
|
||||||
|
'update': FILE_UPDATE,
|
||||||
|
'idl': FILE_IDL,
|
||||||
|
'addin': FILE_ADDIN,
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 754 B |
|
@ -0,0 +1,269 @@
|
||||||
|
# ~ 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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from shutil import copyfile
|
||||||
|
from subprocess import call
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
from conf import (
|
||||||
|
DATA,
|
||||||
|
DIRS,
|
||||||
|
EXTENSION,
|
||||||
|
FILES,
|
||||||
|
INFO,
|
||||||
|
PATHS,
|
||||||
|
TYPE_EXTENSION,
|
||||||
|
log)
|
||||||
|
|
||||||
|
|
||||||
|
def _exists(path):
|
||||||
|
return os.path.exists(path)
|
||||||
|
|
||||||
|
|
||||||
|
def _join(*paths):
|
||||||
|
return os.path.join(*paths)
|
||||||
|
|
||||||
|
|
||||||
|
def _mkdir(path):
|
||||||
|
return os.mkdir(path)
|
||||||
|
|
||||||
|
|
||||||
|
def _save(path, data):
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
f.write(data)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _compress_oxt():
|
||||||
|
log.info('Compress OXT extension...')
|
||||||
|
|
||||||
|
path = DIRS['files']
|
||||||
|
if not _exists(path):
|
||||||
|
_mkdir(path)
|
||||||
|
|
||||||
|
path_oxt = _join(path, FILES['oxt'])
|
||||||
|
|
||||||
|
z = zipfile.ZipFile(path_oxt, 'w', compression=zipfile.ZIP_DEFLATED)
|
||||||
|
root_len = len(os.path.abspath(DIRS['source']))
|
||||||
|
for root, dirs, files in os.walk(DIRS['source']):
|
||||||
|
relative = os.path.abspath(root)[root_len:]
|
||||||
|
for f in files:
|
||||||
|
fullpath = _join(root, f)
|
||||||
|
file_name = _join(relative, f)
|
||||||
|
if file_name == FILES['idl']:
|
||||||
|
continue
|
||||||
|
z.write(fullpath, file_name, zipfile.ZIP_DEFLATED)
|
||||||
|
z.close()
|
||||||
|
|
||||||
|
log.info('Extension OXT created sucesfully...')
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _install_and_test():
|
||||||
|
path_oxt = (_join(DIRS['files'], FILES['oxt']),)
|
||||||
|
call(PATHS['install'] + path_oxt)
|
||||||
|
log.info('Install extension sucesfully...')
|
||||||
|
log.info('Start LibreOffice...')
|
||||||
|
call(PATHS['soffice'])
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_new():
|
||||||
|
path_source = DIRS['source']
|
||||||
|
if not _exists(path_source):
|
||||||
|
return True
|
||||||
|
|
||||||
|
msg = f'Path: {path_source}, exists, delete first'
|
||||||
|
log.error(msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _create_new_directories():
|
||||||
|
path_source = DIRS['source']
|
||||||
|
_mkdir(path_source)
|
||||||
|
path = _join(path_source, DIRS['meta'])
|
||||||
|
_mkdir(path)
|
||||||
|
path = _join(path_source, DIRS['description'])
|
||||||
|
_mkdir(path)
|
||||||
|
path = _join(path_source, DIRS['images'])
|
||||||
|
_mkdir(path)
|
||||||
|
path = _join(path_source, DIRS['registration'])
|
||||||
|
_mkdir(path)
|
||||||
|
|
||||||
|
if DIRS['pythonpath']:
|
||||||
|
path = _join(path_source, DIRS['pythonpath'])
|
||||||
|
_mkdir(path)
|
||||||
|
|
||||||
|
path = DIRS['files']
|
||||||
|
if not _exists(path):
|
||||||
|
_mkdir(path)
|
||||||
|
|
||||||
|
msg = 'Created directories...'
|
||||||
|
log.info(msg)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _create_new_files():
|
||||||
|
path_source = DIRS['source']
|
||||||
|
|
||||||
|
for k, v in INFO.items():
|
||||||
|
file_name = f'license_{k}.txt'
|
||||||
|
path = _join(path_source, DIRS['registration'], file_name)
|
||||||
|
_save(path, v['license'])
|
||||||
|
|
||||||
|
if TYPE_EXTENSION > 1:
|
||||||
|
path = _join(path_source, FILES['idl'])
|
||||||
|
_save(path, DATA['idl'])
|
||||||
|
|
||||||
|
path = _join(path_source, FILES['py'])
|
||||||
|
_save(path, DATA['py'])
|
||||||
|
|
||||||
|
msg = 'Created files...'
|
||||||
|
log.info(msg)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_update():
|
||||||
|
if TYPE_EXTENSION == 1:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not _exists(PATHS['idlc']):
|
||||||
|
msg = 'Binary: "idlc" not found'
|
||||||
|
log.error(msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not _exists(PATHS['include']):
|
||||||
|
msg = 'Directory: "include" not found'
|
||||||
|
log.error(msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not _exists(PATHS['regmerge']):
|
||||||
|
msg = 'Binary: "regmerge" not found'
|
||||||
|
log.error(msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
path = _join(DIRS['source'], FILES['idl'])
|
||||||
|
if not _exists(path):
|
||||||
|
msg = f'File: "{FILES["idl"]}" not found'
|
||||||
|
log.error(msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _compile_idl():
|
||||||
|
if TYPE_EXTENSION == 1:
|
||||||
|
return
|
||||||
|
|
||||||
|
log.info('Compilate IDL...')
|
||||||
|
path_rdb = _join(DIRS['source'], FILES['rdb'])
|
||||||
|
path_urd = _join(DIRS['source'], FILES['urd'])
|
||||||
|
|
||||||
|
path = _join(DIRS['source'], FILES['idl'])
|
||||||
|
call([PATHS['idlc'], '-I', PATHS['include'], path])
|
||||||
|
call([PATHS['regmerge'], path_rdb, '/UCR', path_urd])
|
||||||
|
os.remove(path_urd)
|
||||||
|
|
||||||
|
log.info('Compilate IDL sucesfully...')
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _update_files():
|
||||||
|
path_source = DIRS['source']
|
||||||
|
|
||||||
|
for k, v in INFO.items():
|
||||||
|
file_name = FILES['ext_desc'].format(k)
|
||||||
|
path = _join(path_source, DIRS['description'], file_name)
|
||||||
|
_save(path, v['description'])
|
||||||
|
|
||||||
|
path_logo = EXTENSION['icon'][0]
|
||||||
|
if _exists(path_logo):
|
||||||
|
file_name = EXTENSION['icon'][1]
|
||||||
|
path = _join(path_source, DIRS['images'], file_name)
|
||||||
|
copyfile(path_logo, path)
|
||||||
|
|
||||||
|
files = os.listdir(DIRS['images'])
|
||||||
|
for f in files:
|
||||||
|
if f[-3:].lower() == 'bmp':
|
||||||
|
source = _join(DIRS['images'], f)
|
||||||
|
target = _join(path_source, DIRS['images'], f)
|
||||||
|
copyfile(source, target)
|
||||||
|
|
||||||
|
path = _join(path_source, DIRS['meta'], FILES['manifest'])
|
||||||
|
_save(path, DATA['manifest'])
|
||||||
|
|
||||||
|
path = _join(path_source, FILES['addons'])
|
||||||
|
_save(path, DATA['addons'])
|
||||||
|
|
||||||
|
path = _join(path_source, FILES['description'])
|
||||||
|
_save(path, DATA['description'])
|
||||||
|
|
||||||
|
if TYPE_EXTENSION == 3:
|
||||||
|
path = _join(path_source, FILES['addin'])
|
||||||
|
_save(path, DATA['addin'])
|
||||||
|
|
||||||
|
_compile_idl()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _new():
|
||||||
|
if not _validate_new():
|
||||||
|
return
|
||||||
|
|
||||||
|
_create_new_directories()
|
||||||
|
_create_new_files()
|
||||||
|
_update_files()
|
||||||
|
|
||||||
|
msg = f"New extension: {EXTENSION['name']} make sucesfully...\n"
|
||||||
|
msg += '\tNow, you can install and test: zaz.py -i'
|
||||||
|
log.info(msg)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
if args.new:
|
||||||
|
_new()
|
||||||
|
return
|
||||||
|
|
||||||
|
if not _validate_update():
|
||||||
|
return
|
||||||
|
|
||||||
|
_update_files()
|
||||||
|
_compress_oxt()
|
||||||
|
|
||||||
|
if args.install:
|
||||||
|
_install_and_test()
|
||||||
|
|
||||||
|
log.info('Extension make sucesfully...')
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _process_command_line_arguments():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Make LibreOffice extensions')
|
||||||
|
parser.add_argument('-i', '--install', dest='install', action='store_true',
|
||||||
|
default=False, required=False)
|
||||||
|
parser.add_argument('-n', '--new', dest='new', action='store_true',
|
||||||
|
default=False, required=False)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
args = _process_command_line_arguments()
|
||||||
|
main(args)
|
||||||
|
|
Loading…
Reference in New Issue