Add support for execute dialogs into documents
This commit is contained in:
parent
114d10fc14
commit
cbbc7772c4
|
@ -1,3 +1,8 @@
|
|||
v 0.8.0 [13-oct-2019]
|
||||
- Generate manifest
|
||||
- Add support for execute dialogs in documents.
|
||||
|
||||
|
||||
v 0.7.0 [27-sep-2019]
|
||||
- Add support for InputBox and documents
|
||||
|
||||
|
|
|
@ -205,6 +205,7 @@ PATHS = {
|
|||
'regmerge': '/usr/lib/libreoffice/program/regmerge',
|
||||
'soffice': ('soffice', PROGRAM, FILE_TEST),
|
||||
'install': ('unopkg', 'add', '-v', '-f', '-s'),
|
||||
'profile': '/home/mau/.config/libreoffice/4/user',
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,20 +428,6 @@ FILE_ADDONS = f"""<?xml version='1.0' encoding='UTF-8'?>
|
|||
"""
|
||||
|
||||
|
||||
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"/>
|
||||
<manifest:file-entry manifest:full-path="Office/{FILES['shortcut']}" manifest:media-type="application/vnd.sun.star.configuration-data"/>{NODE_ADDONS}
|
||||
</manifest:manifest>
|
||||
"""
|
||||
|
||||
|
||||
FILE_UPDATE = ''
|
||||
if URL_XML_UPDATE:
|
||||
FILE_UPDATE = f"""<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
@ -625,9 +612,16 @@ FILE_SHORTCUTS = f"""<?xml version="1.0" encoding="UTF-8"?>
|
|||
"""
|
||||
|
||||
|
||||
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 = {
|
||||
'py': FILE_PY,
|
||||
'manifest': FILE_MANIFEST,
|
||||
'manifest': DATA_MANIFEST,
|
||||
'description': FILE_DESCRIPTION,
|
||||
'addons': FILE_ADDONS,
|
||||
'update': FILE_UPDATE,
|
||||
|
|
|
@ -576,6 +576,10 @@ class LODocument(object):
|
|||
def title(self, value):
|
||||
self.obj.setTitle(value)
|
||||
|
||||
@property
|
||||
def uid(self):
|
||||
return self.obj.RuntimeUID
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type_doc
|
||||
|
@ -2656,16 +2660,21 @@ class LODialog(object):
|
|||
def _create(self, properties):
|
||||
path = properties.pop('Path', '')
|
||||
if path:
|
||||
dp = create_instance('com.sun.star.awt.DialogProvider2', True)
|
||||
dp = create_instance('com.sun.star.awt.DialogProvider', True)
|
||||
return dp.createDialog(_path_url(path))
|
||||
|
||||
if 'Library' in properties:
|
||||
location = properties['Location']
|
||||
if 'Location' in properties:
|
||||
location = properties.get('Location', 'application')
|
||||
library = properties.get('Library', 'Standard')
|
||||
if location == 'user':
|
||||
location = 'application'
|
||||
dp = create_instance('com.sun.star.awt.DialogProvider2', True)
|
||||
dp = create_instance('com.sun.star.awt.DialogProvider', True)
|
||||
path = 'vnd.sun.star.script:{}.{}?location={}'.format(
|
||||
properties['Library'], properties['Name'], location)
|
||||
library, properties['Name'], location)
|
||||
if location == 'document':
|
||||
uid = get_document().uid
|
||||
path = 'vnd.sun.star.tdoc:/{}/Dialogs/{}/{}.xml'.format(
|
||||
uid, library, properties['Name'])
|
||||
return dp.createDialog(path)
|
||||
|
||||
dlg = create_instance('com.sun.star.awt.UnoControlDialog', True)
|
||||
|
@ -2678,8 +2687,20 @@ class LODialog(object):
|
|||
|
||||
return dlg
|
||||
|
||||
def _init_controls(self):
|
||||
def _get_type_control(self, name):
|
||||
types = {
|
||||
'stardiv.Toolkit.UnoFixedTextControl': 'label',
|
||||
'stardiv.Toolkit.UnoButtonControl': 'button',
|
||||
'stardiv.Toolkit.UnoEditControl': 'text',
|
||||
}
|
||||
return types[name]
|
||||
|
||||
def _init_controls(self):
|
||||
for control in self.obj.getControls():
|
||||
tipo = self._get_type_control(control.ImplementationName)
|
||||
name = control.Model.Name
|
||||
control = get_custom_class(tipo, control)
|
||||
setattr(self, name, control)
|
||||
return
|
||||
|
||||
@property
|
||||
|
@ -2699,23 +2720,8 @@ class LODialog(object):
|
|||
self._connect_listeners()
|
||||
|
||||
def _connect_listeners(self):
|
||||
|
||||
return
|
||||
|
||||
def _add_listeners(self, control):
|
||||
if self.events is None:
|
||||
return
|
||||
|
||||
listeners = {
|
||||
'addActionListener': EventsButton,
|
||||
'addMouseListener': EventsMouse,
|
||||
}
|
||||
for key, value in listeners.items():
|
||||
if hasattr(control.obj, key):
|
||||
if control.type == 'grid' and key == 'addMouseListener':
|
||||
control.obj.addMouseListener(EventsMouseGrid(self.events))
|
||||
continue
|
||||
getattr(control.obj, key)(listeners[key](self.events))
|
||||
for control in self.obj.getControls():
|
||||
add_listeners(self._events, control, control.Model.Name)
|
||||
return
|
||||
|
||||
def open(self):
|
||||
|
@ -2740,23 +2746,6 @@ class LODialog(object):
|
|||
}
|
||||
return services[control]
|
||||
|
||||
# ~ def _get_custom_class(self, tipo, obj):
|
||||
# ~ classes = {
|
||||
# ~ 'label': UnoLabel,
|
||||
# ~ 'button': UnoButton,
|
||||
# ~ 'text': UnoText,
|
||||
# ~ 'listbox': UnoListBox,
|
||||
# ~ 'grid': UnoGrid,
|
||||
# ~ 'link': UnoLink,
|
||||
# ~ 'tab': UnoTab,
|
||||
# ~ 'roadmap': UnoRoadmap,
|
||||
# ~ 'image': UnoImage,
|
||||
# ~ 'radio': UnoRadio,
|
||||
# ~ 'groupbox': UnoGroupBox,
|
||||
# ~ 'tree': UnoTree,
|
||||
# ~ }
|
||||
# ~ return classes[tipo](obj)
|
||||
|
||||
def _set_column_model(self, columns):
|
||||
#~ https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1grid_1_1XGridColumn.html
|
||||
column_model = create_instance('com.sun.star.awt.grid.DefaultGridColumnModel', True)
|
||||
|
|
184
source/zaz.py
184
source/zaz.py
|
@ -19,11 +19,16 @@
|
|||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import zipfile
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from shutil import copyfile
|
||||
from subprocess import call
|
||||
import zipfile
|
||||
from xml.etree import ElementTree as ET
|
||||
from xml.dom.minidom import parseString
|
||||
|
||||
|
||||
from conf import (
|
||||
DATA,
|
||||
|
@ -37,6 +42,83 @@ from conf import (
|
|||
log)
|
||||
|
||||
|
||||
class LiboXML(object):
|
||||
TYPES = {
|
||||
'py': 'application/vnd.sun.star.uno-component;type=Python',
|
||||
'zip': 'application/binary',
|
||||
'xcu': 'application/vnd.sun.star.configuration-data',
|
||||
'rdb': 'application/vnd.sun.star.uno-typelibrary;type=RDB',
|
||||
'xcs': 'application/vnd.sun.star.configuration-schema',
|
||||
'help': 'application/vnd.sun.star.help',
|
||||
}
|
||||
NAME_SPACES = {
|
||||
'manifest_version': '1.2',
|
||||
'manifest': 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0',
|
||||
'xmlns:loext': 'urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0',
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self._manifest = None
|
||||
self._paths = []
|
||||
|
||||
def _save_path(self, attr):
|
||||
self._paths.append(attr['{{{}}}full-path'.format(self.NAME_SPACES['manifest'])])
|
||||
return
|
||||
|
||||
def _clean(self, name, nodes):
|
||||
has_words = re.compile('\\w')
|
||||
|
||||
if not re.search(has_words, str(nodes.tail)):
|
||||
nodes.tail = ''
|
||||
if not re.search(has_words, str(nodes.text)):
|
||||
nodes.text = ''
|
||||
|
||||
for node in nodes:
|
||||
if name == 'manifest':
|
||||
self._save_path(node.attrib)
|
||||
if not re.search(has_words, str(node.tail)):
|
||||
node.tail = ''
|
||||
if not re.search(has_words, str(node.text)):
|
||||
node.text = ''
|
||||
return
|
||||
|
||||
def new_manifest(self, data):
|
||||
attr = {
|
||||
'manifest:version': self.NAME_SPACES['manifest_version'],
|
||||
'xmlns:manifest': self.NAME_SPACES['manifest'],
|
||||
'xmlns:loext': self.NAME_SPACES['xmlns:loext'],
|
||||
}
|
||||
self._manifest = ET.Element('manifest:manifest', attr)
|
||||
return self.add_data_manifest(data)
|
||||
|
||||
def parse_manifest(self, data):
|
||||
ET.register_namespace('manifest', self.NAME_SPACES['manifest'])
|
||||
self._manifest = ET.fromstring(data)
|
||||
data = {'xmlns:loext': self.NAME_SPACES['xmlns:loext']}
|
||||
self._manifest.attrib.update(**data)
|
||||
self._clean('manifest', self._manifest)
|
||||
return
|
||||
|
||||
def add_data_manifest(self, data):
|
||||
node_name = 'manifest:file-entry'
|
||||
attr = {
|
||||
'manifest:full-path': '',
|
||||
'manifest:media-type': '',
|
||||
}
|
||||
for path in data:
|
||||
if path in self._paths:
|
||||
continue
|
||||
ext = path.split('.')[-1]
|
||||
attr['manifest:full-path'] = path
|
||||
attr['manifest:media-type'] = self.TYPES.get(ext, '')
|
||||
ET.SubElement(self._manifest, node_name, attr)
|
||||
return self._get_xml(self._manifest)
|
||||
|
||||
def _get_xml(self, doc):
|
||||
xml = parseString(ET.tostring(doc, encoding='utf-8'))
|
||||
return xml.toprettyxml(indent=' ', encoding='utf-8').decode('utf-8')
|
||||
|
||||
|
||||
def _exists(path):
|
||||
return os.path.exists(path)
|
||||
|
||||
|
@ -222,8 +304,11 @@ def _update_files():
|
|||
target = _join(path_source, 'pythonpath', source)
|
||||
copyfile(source, target)
|
||||
|
||||
xml = LiboXML()
|
||||
|
||||
path = _join(path_source, DIRS['meta'], FILES['manifest'])
|
||||
_save(path, DATA['manifest'])
|
||||
data = xml.new_manifest(DATA['manifest'])
|
||||
_save(path, data)
|
||||
|
||||
path = _join(path_source, DIRS['office'])
|
||||
_mkdir(path)
|
||||
|
@ -265,7 +350,96 @@ def _new():
|
|||
return
|
||||
|
||||
|
||||
def _get_info_path(path):
|
||||
path, filename = os.path.split(path)
|
||||
name, extension = os.path.splitext(filename)
|
||||
return (path, filename, name, extension)
|
||||
|
||||
|
||||
def _zip_embed(source, files):
|
||||
PATH = 'Scripts/python/'
|
||||
EASYMACRO = 'easymacro.'
|
||||
|
||||
p, f, name, e = _get_info_path(source)
|
||||
now = datetime.now().strftime('_%Y%m%d_%H%M%S')
|
||||
path_source = _join(p, name + now + e)
|
||||
copyfile(source, path_source)
|
||||
target = source
|
||||
|
||||
with zipfile.PyZipFile(EASYMACRO + 'zip', mode='w') as zf:
|
||||
zf.writepy(EASYMACRO + 'py')
|
||||
|
||||
xml = LiboXML()
|
||||
|
||||
path_easymacro = PATH + EASYMACRO + 'zip'
|
||||
names = [f[1] for f in files] + [path_easymacro]
|
||||
nodes = []
|
||||
with zipfile.ZipFile(target, 'w', compression=zipfile.ZIP_DEFLATED) as zt:
|
||||
with zipfile.ZipFile(path_source, compression=zipfile.ZIP_DEFLATED) as zs:
|
||||
for name in zs.namelist():
|
||||
if FILES['manifest'] in name:
|
||||
path_manifest = name
|
||||
xml_manifest = zs.open(name).read()
|
||||
elif name in names:
|
||||
continue
|
||||
else:
|
||||
zt.writestr(name, zs.open(name).read())
|
||||
|
||||
data = []
|
||||
for path, name in files:
|
||||
data.append(name)
|
||||
zt.write(path, name)
|
||||
|
||||
zt.write(EASYMACRO + 'zip', path_easymacro)
|
||||
data.append(path_easymacro)
|
||||
|
||||
xml.parse_manifest(xml_manifest)
|
||||
xml_manifest = xml.add_data_manifest(data)
|
||||
zt.writestr(path_manifest, xml_manifest)
|
||||
|
||||
os.unlink(EASYMACRO + 'zip')
|
||||
return
|
||||
|
||||
|
||||
def _embed(args):
|
||||
PATH = 'Scripts/python'
|
||||
PYTHONPATH = 'pythonpath'
|
||||
|
||||
doc = args.document
|
||||
if not doc:
|
||||
msg = '-d/--document Path file to embed is mandatory'
|
||||
log.error(msg)
|
||||
return
|
||||
if not _exists(doc):
|
||||
msg = 'Path file not exists'
|
||||
log.error(msg)
|
||||
return
|
||||
|
||||
files = []
|
||||
if args.files:
|
||||
files = args.files.split(',')
|
||||
source = _join(PATHS['profile'], PATH)
|
||||
content = os.listdir(source)
|
||||
if PYTHONPATH in content:
|
||||
content.remove(PYTHONPATH)
|
||||
|
||||
if files:
|
||||
files = [(_join(source, f), _join(PATH, f)) for f in files if f in content]
|
||||
else:
|
||||
files = [(_join(source, f), _join(PATH, f)) for f in content]
|
||||
|
||||
_zip_embed(doc, files)
|
||||
|
||||
log.info('Embedded macros successfully...')
|
||||
return
|
||||
|
||||
|
||||
|
||||
def main(args):
|
||||
if args.embed:
|
||||
_embed(args)
|
||||
return
|
||||
|
||||
if args.new:
|
||||
_new()
|
||||
return
|
||||
|
@ -279,7 +453,7 @@ def main(args):
|
|||
if args.install:
|
||||
_install_and_test()
|
||||
|
||||
log.info('Extension make sucesfully...')
|
||||
log.info('Extension make successfully...')
|
||||
return
|
||||
|
||||
|
||||
|
@ -290,6 +464,10 @@ def _process_command_line_arguments():
|
|||
default=False, required=False)
|
||||
parser.add_argument('-n', '--new', dest='new', action='store_true',
|
||||
default=False, required=False)
|
||||
parser.add_argument('-e', '--embed', dest='embed', action='store_true',
|
||||
default=False, required=False)
|
||||
parser.add_argument('-d', '--document', dest='document', default='')
|
||||
parser.add_argument('-f', '--files', dest='files', default='')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue