Add support for spanish

This commit is contained in:
Mauricio Baeza 2019-10-28 22:15:02 -06:00
commit d93665355f
14 changed files with 1594 additions and 111 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
__pycache__/
*.py[cod]
*.po~
*.log
images/

View File

@ -1,2 +1,2 @@
0.1.0
0.2.0

View File

@ -26,7 +26,7 @@ import logging
TYPE_EXTENSION = 1
# ~ https://semver.org/
VERSION = '0.1.0'
VERSION = '0.2.0'
# ~ Your great extension name, not used spaces
NAME = 'ZAZPip'
@ -207,6 +207,8 @@ PATHS = {
'soffice': ('soffice', PROGRAM, FILE_TEST),
'install': ('unopkg', 'add', '-v', '-f', '-s'),
'profile': '/home/mau/.config/libreoffice/4/user',
'gettext': PATH_PYGETTEXT,
'msgmerge': PATH_MSGMERGE,
}

File diff suppressed because it is too large Load Diff

BIN
files/ZAZPip_v0.2.0.oxt Normal file

Binary file not shown.

View File

@ -1,10 +1,8 @@
import uno
import unohelper
import os
from com.sun.star.task import XJobExecutor
import easymacro as app
import site
ID_EXTENSION = 'net.elmau.zaz.pip'
SERVICE = ('com.sun.star.task.Job',)
@ -21,11 +19,7 @@ PACKAGES = {
}
# ~ sudoPassword = 'mypass'
# ~ command = 'mount -t vboxsf myfolder /home/myuser/myfolder'.split()
# ~ cmd1 = subprocess.Popen(['echo',sudoPassword], stdout=subprocess.PIPE)
# ~ cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)
# ~ output = cmd2.stdout.read.decode()
_ = app.install_locales(__file__)
class Controllers(object):
@ -52,7 +46,7 @@ class Controllers(object):
return
def cmd_install_pip_action(self, event):
msg = 'Do you want install PIP?'
msg = _('Do you want install PIP?')
if not app.question(msg, 'ZAZ-Pip'):
return
@ -70,20 +64,20 @@ class Controllers(object):
self.d.lst_log.insert('Download PIP...')
data = app.url_open(URL_PIP)
if not data:
msg = 'Do you have internet connection?'
msg = _('Do you have internet connection?')
app.errorbox(msg)
return
app.save_file(path_pip, 'wb', data)
if not app.is_created(path_pip):
msg = 'File PIP not save'
msg = _('File PIP not save')
app.errorbox(msg)
return
self.d.lst_log.insert('PIP save correctly...')
self.d.lst_log.insert(_('PIP save correctly...'))
try:
self.d.lst_log.insert('Start installing PIP...')
self.d.lst_log.insert(_('Start installing PIP...'))
cmd = '"{}" "{}" --user'.format(self.path_python, path_pip)
for line in app.popen(cmd):
if isinstance(line, tuple):
@ -97,10 +91,10 @@ class Controllers(object):
self.d.lbl_pip.value = label
self.d.cmd_install_pip.visible = False
self.d.cmd_admin_pip.visible = True
msg = 'PIP installed sucesfully'
msg = _('PIP installed sucesfully')
app.msgbox(msg)
else:
msg = 'PIP not installed, see log.'
msg = _('PIP not installed, see log')
app.warning(msg)
except Exception as e:
app.errorbox(e)
@ -120,7 +114,6 @@ class Controllers(object):
self.cmd_home_action(None)
return
@app.catch_exception
def cmd_close_action(self, event):
self.d.close()
return
@ -176,7 +169,7 @@ class Controllers(object):
if line:
self.d.lst_package.select()
else:
self.d.lst_package.insert('Not found...', 'error.png', show=False)
self.d.lst_package.insert(_('Not found...'), 'error.png', show=False)
return
def cmd_search_action(self, event):
@ -212,7 +205,7 @@ class Controllers(object):
opt = 'upgrade'
name = self.d.lst_package.value
msg = 'Do you want {}:\n\n{} ?'.format(opt, name)
msg = _('Do you want {}:\n\n{} ?').format(opt, name)
if not app.question(msg, TITLE):
return
@ -238,12 +231,12 @@ class Controllers(object):
def cmd_uninstall_action(self, event):
if not self._states['list']:
msg = 'Select installed package'
msg = _('Select installed package')
app.warning(msg)
return
name = self.d.lst_package.value
msg = 'Do you want uninstall:\n\n{} ?'.format(name)
msg = _('Do you want uninstall:\n\n{} ?').format(name)
if not app.question(msg):
return
@ -254,13 +247,13 @@ class Controllers(object):
def cmd_shell_action(self, name):
if app.IS_WIN:
cmd = '"{}"'.format(self.path_python)
os.startfile(cmd)
app.open_file(cmd)
else:
if app.DESKTOP == 'gnome':
cmd = 'gnome-terminal -- {}'.format(self.path_python)
else:
cmd = 'exec {}'.format(self.path_python)
os.system(cmd)
app.run(cmd)
return
@ -277,7 +270,7 @@ class ZAZPip(unohelper.Base, XJobExecutor):
def _create_dialog(self):
args= {
'Name': 'dialog',
'Title': 'ZAZ-Pip',
'Title': 'ZAZ-PIP',
'Width': 200,
'Height': 220,
}
@ -288,7 +281,7 @@ class ZAZPip(unohelper.Base, XJobExecutor):
args = {
'Type': 'Label',
'Name': 'lbl_title',
'Label': 'ZAZ Pip',
'Label': 'ZAZ PIP',
'Width': 50,
'Height': 15,
'Border': 1,
@ -330,7 +323,7 @@ class ZAZPip(unohelper.Base, XJobExecutor):
exists_pip = True
if not label:
exists_pip = False
label = 'PIP not installed'
label = _('PIP not installed')
args = {
'Type': 'Label',
'Name': 'lbl_pip',
@ -349,7 +342,7 @@ class ZAZPip(unohelper.Base, XJobExecutor):
args = {
'Type': 'Button',
'Name': 'cmd_admin_pip',
'Label': 'Admin PIP',
'Label': _('Admin PIP'),
'Width': 60,
'Height': 18,
'Step': 10,
@ -362,7 +355,7 @@ class ZAZPip(unohelper.Base, XJobExecutor):
args = {
'Type': 'Button',
'Name': 'cmd_install_pip',
'Label': 'Install PIP',
'Label': _('Install PIP'),
'Width': 60,
'Height': 18,
'Step': 10,
@ -400,7 +393,7 @@ class ZAZPip(unohelper.Base, XJobExecutor):
args = {
'Type': 'Label',
'Name': 'lbl_package',
'Label': 'Packages',
'Label': _('Packages'),
'Width': 100,
'Height': 15,
'Border': 1,
@ -432,7 +425,7 @@ class ZAZPip(unohelper.Base, XJobExecutor):
args = {
'Type': 'Button',
'Name': 'cmd_close',
'Label': '~Close',
'Label': _('~Close'),
'Width': 60,
'Height': 18,
'Step': 1,

View File

@ -1,7 +1,7 @@
<?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="net.elmau.zaz.pip" />
<version value="0.1.0" />
<version value="0.2.0" />
<display-name>
<name lang="en">ZAZ Pip</name>
<name lang="es">ZAZ Pip</name>

87
source/locales/base.pot Normal file
View File

@ -0,0 +1,87 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2019-10-19 15:19-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
#: source/ZAZPip.py:49
msgid "Do you want install PIP?"
msgstr ""
#: source/ZAZPip.py:67
msgid "Do you have internet connection?"
msgstr ""
#: source/ZAZPip.py:73
msgid "File PIP not save"
msgstr ""
#: source/ZAZPip.py:76
msgid "PIP save correctly..."
msgstr ""
#: source/ZAZPip.py:80
msgid "Start installing PIP..."
msgstr ""
#: source/ZAZPip.py:94
msgid "PIP installed sucesfully"
msgstr ""
#: source/ZAZPip.py:97
msgid "PIP not installed, see log"
msgstr ""
#: source/ZAZPip.py:173
msgid "Not found..."
msgstr ""
#: source/ZAZPip.py:209
msgid ""
"Do you want {}:\n"
"\n"
"{} ?"
msgstr ""
#: source/ZAZPip.py:235
msgid "Select installed package"
msgstr ""
#: source/ZAZPip.py:240
msgid ""
"Do you want uninstall:\n"
"\n"
"{} ?"
msgstr ""
#: source/ZAZPip.py:327
msgid "PIP not installed"
msgstr ""
#: source/ZAZPip.py:346
msgid "Admin PIP"
msgstr ""
#: source/ZAZPip.py:359
msgid "Install PIP"
msgstr ""
#: source/ZAZPip.py:397
msgid "Packages"
msgstr ""
#: source/ZAZPip.py:429
msgid "~Close"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,88 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2019-10-19 15:19-0500\n"
"PO-Revision-Date: 2019-10-19 15:20-0500\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 2.2.4\n"
"Last-Translator: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: en\n"
#: source/ZAZPip.py:49
msgid "Do you want install PIP?"
msgstr ""
#: source/ZAZPip.py:67
msgid "Do you have internet connection?"
msgstr ""
#: source/ZAZPip.py:73
msgid "File PIP not save"
msgstr ""
#: source/ZAZPip.py:76
msgid "PIP save correctly..."
msgstr ""
#: source/ZAZPip.py:80
msgid "Start installing PIP..."
msgstr ""
#: source/ZAZPip.py:94
msgid "PIP installed sucesfully"
msgstr ""
#: source/ZAZPip.py:97
msgid "PIP not installed, see log"
msgstr ""
#: source/ZAZPip.py:173
msgid "Not found..."
msgstr ""
#: source/ZAZPip.py:209
msgid ""
"Do you want {}:\n"
"\n"
"{} ?"
msgstr ""
#: source/ZAZPip.py:235
msgid "Select installed package"
msgstr ""
#: source/ZAZPip.py:240
msgid ""
"Do you want uninstall:\n"
"\n"
"{} ?"
msgstr ""
#: source/ZAZPip.py:327
msgid "PIP not installed"
msgstr ""
#: source/ZAZPip.py:346
msgid "Admin PIP"
msgstr ""
#: source/ZAZPip.py:359
msgid "Install PIP"
msgstr ""
#: source/ZAZPip.py:397
msgid "Packages"
msgstr ""
#: source/ZAZPip.py:429
msgid "~Close"
msgstr ""

Binary file not shown.

View File

@ -0,0 +1,94 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2019-10-19 15:19-0500\n"
"PO-Revision-Date: 2019-10-19 15:24-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 2.2.4\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: source/ZAZPip.py:49
msgid "Do you want install PIP?"
msgstr "¿Desea instalar PIP?"
#: source/ZAZPip.py:67
msgid "Do you have internet connection?"
msgstr "¿Tiene conexión a Internet?"
#: source/ZAZPip.py:73
msgid "File PIP not save"
msgstr "No se guardo el archivo PIP"
#: source/ZAZPip.py:76
msgid "PIP save correctly..."
msgstr "Archivo PIP guardado correctamente..."
#: source/ZAZPip.py:80
msgid "Start installing PIP..."
msgstr "Iniciando instalación de PIP..."
#: source/ZAZPip.py:94
msgid "PIP installed sucesfully"
msgstr "PIP instalado correctamente"
#: source/ZAZPip.py:97
msgid "PIP not installed, see log"
msgstr "PIP no fue instalado, vea el registro"
#: source/ZAZPip.py:173
msgid "Not found..."
msgstr "No encontrado..."
#: source/ZAZPip.py:209
msgid ""
"Do you want {}:\n"
"\n"
"{} ?"
msgstr ""
"¿Desea {}:\n"
"\n"
"{} ?"
#: source/ZAZPip.py:235
msgid "Select installed package"
msgstr "Seleccione un paquete instalado"
#: source/ZAZPip.py:240
msgid ""
"Do you want uninstall:\n"
"\n"
"{} ?"
msgstr ""
"¿Desea desinstalar:\n"
"\n"
"{} ?"
#: source/ZAZPip.py:327
msgid "PIP not installed"
msgstr "PIP no esta instalado"
#: source/ZAZPip.py:346
msgid "Admin PIP"
msgstr "Administrar PIP"
#: source/ZAZPip.py:359
msgid "Install PIP"
msgstr "Instalar PIP"
#: source/ZAZPip.py:397
msgid "Packages"
msgstr "Paquetes"
#: source/ZAZPip.py:429
msgid "~Close"
msgstr "~Cerrar"

View File

@ -22,6 +22,7 @@ import csv
import ctypes
import datetime
import errno
import gettext
import getpass
import hashlib
import json
@ -40,12 +41,13 @@ import time
import traceback
import zipfile
from collections import OrderedDict
from collections.abc import MutableMapping
# ~ from collections import OrderedDict
# ~ from collections.abc import MutableMapping
from functools import wraps
from operator import itemgetter
from pathlib import Path, PurePath
from pprint import pprint
from enum import IntEnum
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
from string import Template
@ -77,6 +79,7 @@ from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK
from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
from com.sun.star.script import ScriptEventDescriptor
from com.sun.star.lang import XEventListener
from com.sun.star.awt import XActionListener
from com.sun.star.awt import XMouseListener
@ -88,7 +91,15 @@ from com.sun.star.awt import XMenuListener
from com.sun.star.awt import XKeyListener
from com.sun.star.awt import XItemListener
from com.sun.star.awt import XFocusListener
from com.sun.star.awt import XTabListener
class FontSlant(IntEnum):
NONE = 0
OBLIQUE = 1
ITALIC = 2
DONTKNOW = 3
REVERSE_OBLIQUE = 4
REVERSE_ITALIC = 5
try:
from fernet import Fernet, InvalidToken
@ -100,6 +111,7 @@ ID_EXTENSION = ''
DIR = {
'images': 'images',
'locales': 'locales',
}
KEY = {
@ -299,7 +311,6 @@ def info(data):
return
@catch_exception
def debug(*info):
if IS_WIN:
doc = get_document(FILE_NAME_DEBUG)
@ -334,18 +345,17 @@ def run_in_thread(fn):
return run
def now():
return datetime.datetime.now()
def now(only_time=False):
now = datetime.datetime.now()
if only_time:
return now.time()
return now
def today():
return datetime.date.today()
def time():
return datetime.datetime.now().time()
def get_date(year, month, day, hour=-1, minute=-1, second=-1):
if hour > -1 or minute > -1 or second > -1:
h = hour
@ -598,9 +608,6 @@ class LODocument(object):
def _init_values(self):
self._type_doc = get_type_doc(self.obj)
# ~ if self._type_doc == 'base':
# ~ self._cc = self.obj.DatabaseDocument.getCurrentController()
# ~ else:
self._cc = self.obj.getCurrentController()
return
@ -721,10 +728,117 @@ class LODocument(object):
return path_pdf
class FormControlBase(object):
EVENTS = {
'action': 'actionPerformed',
'click': 'mousePressed',
}
TYPES = {
'actionPerformed': 'XActionListener',
'mousePressed': 'XMouseListener',
}
def __init__(self, obj):
self._obj = obj
self._index = -1
self._rules = {}
@property
def obj(self):
return self._obj
@property
def name(self):
return self.obj.Name
@property
def form(self):
return self.obj.getParent()
@property
def index(self):
return self._index
@index.setter
def index(self, value):
self._index = value
@property
def events(self):
return self.form.getScriptEvents(self.index)
def remove_event(self, name=''):
for ev in self.events:
if name and \
ev.EventMethod == self.EVENTS[name] and \
ev.ListenerType == self.TYPES[ev.EventMethod]:
self.form.revokeScriptEvent(self.index,
ev.ListenerType, ev.EventMethod, ev.AddListenerParam)
break
else:
self.form.revokeScriptEvent(self.index,
ev.ListenerType, ev.EventMethod, ev.AddListenerParam)
return
def add_event(self, name, macro):
if not 'name' in macro:
macro['name'] = '{}_{}'.format(self.name, name)
event = ScriptEventDescriptor()
event.AddListenerParam = ''
event.EventMethod = self.EVENTS[name]
event.ListenerType = self.TYPES[event.EventMethod]
event.ScriptCode = _get_url_script(macro)
event.ScriptType = 'Script'
for ev in self.events:
if ev.EventMethod == event.EventMethod and \
ev.ListenerType == event.ListenerType:
self.form.revokeScriptEvent(self.index,
event.ListenerType, event.EventMethod, event.AddListenerParam)
break
self.form.registerScriptEvent(self.index, event)
return
class FormButton(FormControlBase):
def __init__(self, obj):
super().__init__(obj)
class LOForm(ObjectBase):
def __init__(self, obj):
super().__init__(obj)
self._init_controls()
def __getitem__(self, index):
if isinstance(index, int):
return self._controls[index]
else:
return getattr(self, index)
def _get_type_control(self, name):
types = {
# ~ 'stardiv.Toolkit.UnoFixedTextControl': 'label',
'com.sun.star.form.OButtonModel': 'formbutton',
# ~ 'stardiv.Toolkit.UnoEditControl': 'text',
# ~ 'stardiv.Toolkit.UnoRoadmapControl': 'roadmap',
# ~ 'stardiv.Toolkit.UnoFixedHyperlinkControl': 'link',
# ~ 'stardiv.Toolkit.UnoListBoxControl': 'listbox',
}
return types[name]
def _init_controls(self):
self._controls = []
for i, c in enumerate(self.obj.ControlModels):
tipo = self._get_type_control(c.ImplementationName)
control = get_custom_class(tipo, c)
control.index = i
self._controls.append(control)
setattr(self, c.Name, control)
@property
def name(self):
@ -821,6 +935,67 @@ class LOCellStyles(object):
return
class LOImage(object):
TYPES = {
'image/png': 'png',
'image/jpeg': 'jpg',
}
def __init__(self, obj):
self._obj = obj
@property
def obj(self):
return self._obj
@property
def address(self):
return self.obj.Anchor.AbsoluteName
@property
def name(self):
return self.obj.Name
@property
def mimetype(self):
return self.obj.Bitmap.MimeType
@property
def url(self):
return _path_system(self.obj.URL)
@url.setter
def url(self, value):
self.obj.URL = _path_url(value)
@property
def path(self):
return _path_system(self.obj.GraphicURL)
@path.setter
def path(self, value):
self.obj.GraphicURL = _path_url(value)
@property
def visible(self):
return self.obj.Visible
@visible.setter
def visible(self, value):
self_obj.Visible = value
def save(self, path):
if is_dir(path):
p = path
n = self.name
else:
p, fn, n, e = get_info_path(path)
ext = self.TYPES[self.mimetype]
path = join(p, '{}.{}'.format(n, ext))
size = len(self.obj.Bitmap.DIB)
data = self.obj.GraphicStream.readBytes((), size)
data = data[-1].value
save_file(path, 'wb', data)
return path
class LOCalc(LODocument):
def __init__(self, obj):
@ -1069,7 +1244,7 @@ class LOCalcSheet(object):
def _init_values(self):
self._events = None
self._dp = self.obj.getDrawPage()
return
self._images = {i.Name: LOImage(i) for i in self._dp}
@property
def obj(self):
@ -1079,6 +1254,10 @@ class LOCalcSheet(object):
def doc(self):
return self._doc
@property
def images(self):
return self._images
@property
def name(self):
return self._obj.Name
@ -1255,6 +1434,42 @@ class LOWriter(LODocument):
self._cc.select(text)
return
def search(self, options):
descriptor = self.obj.createSearchDescriptor()
descriptor.setSearchString(options.get('Search', ''))
descriptor.SearchCaseSensitive = options.get('CaseSensitive', False)
descriptor.SearchWords = options.get('Words', False)
if 'Attributes' in options:
attr = dict_to_property(options['Attributes'])
descriptor.setSearchAttributes(attr)
if hasattr(descriptor, 'SearchRegularExpression'):
descriptor.SearchRegularExpression = options.get('RegularExpression', False)
if hasattr(descriptor, 'SearchType') and 'Type' in options:
descriptor.SearchType = options['Type']
if options.get('First', False):
found = self.obj.findFirst(descriptor)
else:
found = self.obj.findAll(descriptor)
return found
def replace(self, options):
descriptor = self.obj.createReplaceDescriptor()
descriptor.setSearchString(options['Search'])
descriptor.setReplaceString(options['Replace'])
descriptor.SearchCaseSensitive = options.get('CaseSensitive', False)
descriptor.SearchWords = options.get('Words', False)
if 'Attributes' in options:
attr = dict_to_property(options['Attributes'])
descriptor.setSearchAttributes(attr)
if hasattr(descriptor, 'SearchRegularExpression'):
descriptor.SearchRegularExpression = options.get('RegularExpression', False)
if hasattr(descriptor, 'SearchType') and 'Type' in options:
descriptor.SearchType = options['Type']
found = self.obj.replaceAll(descriptor)
return found
class LOTextRange(object):
@ -1610,6 +1825,10 @@ class LOCellRange(object):
rango.data = self.data
return
def copy(self, source):
self.sheet.obj.copyRange(self.address, source.range_address)
return
def offset(self, row=1, col=0):
ra = self.obj.getRangeAddress()
col = ra.EndColumn + col
@ -1667,6 +1886,10 @@ class LOCellRange(object):
a = self.obj.getRangeAddressesAsString()
return a
@property
def range_address(self):
return self.obj.getRangeAddress()
@property
def current_region(self):
cursor = self.sheet.get_cursor(self.obj[0,0])
@ -1799,6 +2022,36 @@ class LOCellRange(object):
chart.cell = self
return chart
def search(self, options):
descriptor = self.obj.Spreadsheet.createSearchDescriptor()
descriptor.setSearchString(options.get('Search', ''))
descriptor.SearchCaseSensitive = options.get('CaseSensitive', False)
descriptor.SearchWords = options.get('Words', False)
if hasattr(descriptor, 'SearchRegularExpression'):
descriptor.SearchRegularExpression = options.get('RegularExpression', False)
if hasattr(descriptor, 'SearchType') and 'Type' in options:
descriptor.SearchType = options['Type']
if options.get('First', False):
found = self.obj.findFirst(descriptor)
else:
found = self.obj.findAll(descriptor)
return found
def replace(self, options):
descriptor = self.obj.Spreadsheet.createReplaceDescriptor()
descriptor.setSearchString(options['Search'])
descriptor.setReplaceString(options['Replace'])
descriptor.SearchCaseSensitive = options.get('CaseSensitive', False)
descriptor.SearchWords = options.get('Words', False)
if hasattr(descriptor, 'SearchRegularExpression'):
descriptor.SearchRegularExpression = options.get('RegularExpression', False)
if hasattr(descriptor, 'SearchType') and 'Type' in options:
descriptor.SearchType = options['Type']
found = self.obj.replaceAll(descriptor)
return found
class EventsListenerBase(unohelper.Base, XEventListener):
@ -1966,6 +2219,18 @@ class EventsKey(EventsListenerBase, XKeyListener):
return
class EventsTab(EventsListenerBase, XTabListener):
def __init__(self, controller, name):
super().__init__(controller, name)
def activated(self, id):
event_name = '{}_activated'.format(self.name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(id)
return
class EventsKeyWindow(EventsListenerBase, XKeyListener):
"""
event.KeyChar
@ -2067,7 +2332,6 @@ class EventsMenu(EventsListenerBase, XMenuListener):
def itemHighlighted(self, event):
pass
@catch_exception
def itemSelected(self, event):
name = event.Source.getCommand(event.MenuId)
if name.startswith('menu'):
@ -2308,7 +2572,7 @@ class UnoListBox(UnoBaseObject):
@property
def value(self):
return self.obj.SelectedItem
return self.obj.getSelectedItem()
@property
def count(self):
@ -2322,6 +2586,10 @@ class UnoListBox(UnoBaseObject):
self.model.StringItemList = list(sorted(values))
return
def unselect(self):
self.obj.selectItem(self.value, False)
return
def select(self, pos=0):
if isinstance(pos, str):
self.obj.selectItem(pos, True)
@ -2330,7 +2598,7 @@ class UnoListBox(UnoBaseObject):
return
def clear(self):
self.obj.removeItems(0, self.count)
self.model.removeAllItems()
return
def _set_image_url(self, image):
@ -2501,6 +2769,166 @@ class UnoRoadmap(UnoBaseObject):
return
class UnoTree(UnoBaseObject):
def __init__(self, obj, ):
super().__init__(obj)
self._tdm = None
self._data = []
@property
def selection(self):
return self.obj.Selection
@property
def root(self):
if self._tdm is None:
return ''
return self._tdm.Root.DisplayValue
@root.setter
def root(self, value):
self._add_data_model(value)
def _add_data_model(self, name):
tdm = create_instance('com.sun.star.awt.tree.MutableTreeDataModel')
root = tdm.createNode(name, True)
root.DataValue = 0
tdm.setRoot(root)
self.model.DataModel = tdm
self._tdm = self.model.DataModel
self._add_data()
return
@property
def data(self):
return self._data
@data.setter
def data(self, values):
self._data = list(values)
self._add_data()
def _add_data(self):
if not self.data:
return
parents = {}
for node in self.data:
parent = parents.get(node[1], self._tdm.Root)
child = self._tdm.createNode(node[2], False)
child.DataValue = node[0]
parent.appendChild(child)
parents[node[0]] = child
self.obj.expandNode(self._tdm.Root)
return
class UnoPages(UnoBaseObject):
def __init__(self, obj):
super().__init__(obj)
self._events = None
def __getitem__(self, index):
return self.get_sheet(index)
@property
def current(self):
return self.obj.getActiveTabID()
def get_sheet(self, id):
if isinstance(id, int):
sheet = self.obj.Controls[id-1]
else:
sheet = self.obj.getControl(id.lower())
return sheet
@property
def sheets(self):
return self._sheets
@sheets.setter
def sheets(self, values):
i = len(self.obj.Controls)
for title in values:
i += 1
sheet = self.model.createInstance('com.sun.star.awt.UnoPageModel')
sheet.Title = title
self.model.insertByName('sheet{}'.format(i), sheet)
return
def insert(self, title):
id = len(self.obj.Controls) + 1
sheet = self.model.createInstance('com.sun.star.awt.UnoPageModel')
sheet.Title = title
self.model.insertByName('sheet{}'.format(id), sheet)
return id
def remove(self, id):
sheet = self.get_sheet(id)
for control in sheet.getControls():
sheet.Model.removeByName(control.Model.Name)
sheet.removeControl(control)
# ~ self._model.removeByName('page_{}'.format(ID))
self.obj.removeTab(id)
return
def activate(self, id):
self.obj.activateTab(id)
return
@property
def events(self):
return self._events
@events.setter
def events(self, controllers):
self._events = controllers
def _special_properties(self, tipo, properties):
columns = properties.pop('Columns', ())
if tipo == 'grid':
properties['ColumnModel'] = self._set_column_model(columns)
elif tipo == 'button' and 'ImageURL' in properties:
properties['ImageURL'] = self._set_image_url(properties['ImageURL'])
elif tipo == 'roadmap':
if not 'Height' in properties:
properties['Height'] = self.height
if 'Title' in properties:
properties['Text'] = properties.pop('Title')
elif tipo == 'pages':
if not 'Width' in properties:
properties['Width'] = self.width
if not 'Height' in properties:
properties['Height'] = self.height
return properties
def add_control(self, id, properties):
tipo = properties.pop('Type').lower()
root = properties.pop('Root', '')
sheets = properties.pop('Sheets', ())
properties = self._special_properties(tipo, properties)
sheet = self.get_sheet(id)
sheet_model = sheet.getModel()
model = sheet_model.createInstance(get_control_model(tipo))
set_properties(model, properties)
name = properties['Name']
sheet_model.insertByName(name, model)
control = sheet.getControl(name)
add_listeners(self.events, control, name)
control = get_custom_class(tipo, control)
if tipo == 'tree' and root:
control.root = root
elif tipo == 'pages' and sheets:
control.sheets = sheets
setattr(self, name, control)
return
def get_custom_class(tipo, obj):
classes = {
'label': UnoLabel,
@ -2510,15 +2938,34 @@ def get_custom_class(tipo, obj):
'grid': UnoGrid,
'link': UnoLabelLink,
'roadmap': UnoRoadmap,
# ~ 'tab': UnoTab,
'tree': UnoTree,
'pages': UnoPages,
# ~ 'image': UnoImage,
# ~ 'radio': UnoRadio,
# ~ 'groupbox': UnoGroupBox,
# ~ 'tree': UnoTree,
'formbutton': FormButton,
}
return classes[tipo](obj)
def get_control_model(control):
services = {
'label': 'com.sun.star.awt.UnoControlFixedTextModel',
'link': 'com.sun.star.awt.UnoControlFixedHyperlinkModel',
'text': 'com.sun.star.awt.UnoControlEditModel',
'listbox': 'com.sun.star.awt.UnoControlListBoxModel',
'button': 'com.sun.star.awt.UnoControlButtonModel',
'roadmap': 'com.sun.star.awt.UnoControlRoadmapModel',
'grid': 'com.sun.star.awt.grid.UnoControlGridModel',
'tree': 'com.sun.star.awt.tree.TreeControlModel',
'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel',
'image': 'com.sun.star.awt.UnoControlImageControlModel',
'radio': 'com.sun.star.awt.UnoControlRadioButtonModel',
'pages': 'com.sun.star.awt.UnoMultiPageModel',
}
return services[control]
def add_listeners(events, control, name=''):
listeners = {
'addActionListener': EventsButton,
@ -2526,6 +2973,7 @@ def add_listeners(events, control, name=''):
'addItemListener': EventsItem,
'addFocusListener': EventsFocus,
'addKeyListener': EventsKey,
'addTabListener': EventsTab,
}
if hasattr(control, 'obj'):
control = contro.obj
@ -3035,11 +3483,12 @@ class LODialog(object):
def _get_type_control(self, name):
types = {
'stardiv.Toolkit.UnoFixedTextControl': 'label',
'stardiv.Toolkit.UnoButtonControl': 'button',
'stardiv.Toolkit.UnoEditControl': 'text',
'stardiv.Toolkit.UnoRoadmapControl': 'roadmap',
'stardiv.Toolkit.UnoFixedHyperlinkControl': 'link',
'stardiv.Toolkit.UnoEditControl': 'text',
'stardiv.Toolkit.UnoButtonControl': 'button',
'stardiv.Toolkit.UnoListBoxControl': 'listbox',
'stardiv.Toolkit.UnoRoadmapControl': 'roadmap',
'stardiv.Toolkit.UnoMultiPageControl': 'pages',
}
return types[name]
@ -3126,17 +3575,18 @@ class LODialog(object):
def _get_control_model(self, control):
services = {
'button': 'com.sun.star.awt.UnoControlButtonModel',
'grid': 'com.sun.star.awt.grid.UnoControlGridModel',
'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel',
'image': 'com.sun.star.awt.UnoControlImageControlModel',
'label': 'com.sun.star.awt.UnoControlFixedTextModel',
'link': 'com.sun.star.awt.UnoControlFixedHyperlinkModel',
'listbox': 'com.sun.star.awt.UnoControlListBoxModel',
'radio': 'com.sun.star.awt.UnoControlRadioButtonModel',
'roadmap': 'com.sun.star.awt.UnoControlRoadmapModel',
'text': 'com.sun.star.awt.UnoControlEditModel',
'listbox': 'com.sun.star.awt.UnoControlListBoxModel',
'button': 'com.sun.star.awt.UnoControlButtonModel',
'roadmap': 'com.sun.star.awt.UnoControlRoadmapModel',
'grid': 'com.sun.star.awt.grid.UnoControlGridModel',
'tree': 'com.sun.star.awt.tree.TreeControlModel',
'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel',
'image': 'com.sun.star.awt.UnoControlImageControlModel',
'radio': 'com.sun.star.awt.UnoControlRadioButtonModel',
'pages': 'com.sun.star.awt.UnoMultiPageModel',
}
return services[control]
@ -3172,10 +3622,19 @@ class LODialog(object):
properties['Height'] = self.height
if 'Title' in properties:
properties['Text'] = properties.pop('Title')
elif tipo == 'pages':
if not 'Width' in properties:
properties['Width'] = self.width
if not 'Height' in properties:
properties['Height'] = self.height
return properties
def add_control(self, properties):
tipo = properties.pop('Type').lower()
root = properties.pop('Root', '')
sheets = properties.pop('Sheets', ())
properties = self._special_properties(tipo, properties)
model = self.model.createInstance(self._get_control_model(tipo))
set_properties(model, properties)
@ -3184,6 +3643,13 @@ class LODialog(object):
control = self.obj.getControl(name)
add_listeners(self.events, control, name)
control = get_custom_class(tipo, control)
if tipo == 'tree' and root:
control.root = root
elif tipo == 'pages' and sheets:
control.sheets = sheets
control.events = self.events
setattr(self, name, control)
return
@ -3402,7 +3868,7 @@ def get_document(title=''):
return doc
for d in desktop.getComponents():
if d.Title == title:
if hasattr(d, 'Title') and d.Title == title:
doc = d
break
@ -3595,6 +4061,10 @@ def get_path_extension(id):
return path
def get_home():
return Path.home()
# ~ Export ok
def inputbox(message, default='', title=TITLE, echochar=''):
@ -3789,6 +4259,7 @@ def url_open(url, options={}, json=False):
req = Request(url)
try:
response = urlopen(req)
# ~ response.info()
except HTTPError as e:
error(e)
except URLError as e:
@ -4419,6 +4890,24 @@ def format(template, data):
return result
def _get_url_script(macro):
macro['language'] = macro.get('language', 'Python')
macro['location'] = macro.get('location', 'user')
data = macro.copy()
if data['language'] == 'Python':
data['module'] = '.py$'
elif data['language'] == 'Basic':
data['module'] = '.{}.'.format(macro['module'])
if macro['location'] == 'user':
data['location'] = 'application'
else:
data['module'] = '.'
url = 'vnd.sun.star.script:{library}{module}{name}?language={language}&location={location}'
path = url.format(**data)
return path
def _call_macro(macro):
#~ https://wiki.openoffice.org/wiki/Documentation/DevGuide/Scripting/Scripting_Framework_URI_Specification
name = 'com.sun.star.script.provider.MasterScriptProviderFactory'
@ -4439,6 +4928,7 @@ def _call_macro(macro):
args = macro.get('args', ())
url = 'vnd.sun.star.script:{library}{module}{name}?language={language}&location={location}'
path = url.format(**data)
script = factory.createScriptProvider('').getScript(path)
return script.invoke(args, None, None)[0]
@ -4665,6 +5155,7 @@ def import_csv(path, **kwargs):
rows = tuple(csv.reader(f, **kwargs))
return rows
def export_csv(path, data, **kwargs):
with open(path, 'w') as f:
writer = csv.writer(f, **kwargs)
@ -4672,6 +5163,19 @@ def export_csv(path, data, **kwargs):
return
def install_locales(path, domain='base', dir_locales=DIR['locales']):
p, *_ = get_info_path(path)
path_locales = join(p, dir_locales)
try:
lang = gettext.translation(domain, path_locales, languages=[LANG])
lang.install()
_ = lang.gettext
except Exception as e:
from gettext import gettext as _
error(e)
return _
class LIBOServer(object):
HOST = 'localhost'
PORT = '8100'

60
zaz.py
View File

@ -33,6 +33,7 @@ from xml.dom.minidom import parseString
from conf import (
DATA,
DIRS,
DOMAIN,
EXTENSION,
FILES,
INFO,
@ -138,6 +139,19 @@ def _save(path, data):
return
def _get_files(path, filters=''):
paths = []
if filters in ('*', '*.*'):
filters = ''
for folder, _, files in os.walk(path):
if filters:
pattern = re.compile(r'\.(?:{})$'.format(filters), re.IGNORECASE)
paths += [_join(folder, f) for f in files if pattern.search(f)]
else:
paths += files
return paths
def _compress_oxt():
log.info('Compress OXT extension...')
@ -435,8 +449,50 @@ def _embed(args):
return
def _locales(args):
EASYMACRO = 'easymacro.py'
if args.files:
files = args.files.split(',')
else:
files = _get_files(DIRS['source'], 'py')
paths = ' '.join([f for f in files if not EASYMACRO in f])
path_pot = _join(DIRS['source'], DIRS['locales'], '{}.pot'.format(DOMAIN))
call([PATHS['gettext'], '-o', path_pot, paths])
log.info('POT generate successfully...')
return
def _update():
path_locales = _join(DIRS['source'], DIRS['locales'])
path_pot = _join(DIRS['source'], DIRS['locales'], '{}.pot'.format(DOMAIN))
if not _exists(path_pot):
log.error('Not exists file POT...')
return
files = _get_files(path_locales, 'po')
if not files:
log.error('First, generate files PO...')
return
for f in files:
call([PATHS['msgmerge'], '-U', f, path_pot])
log.info('\tUpdate: {}'.format(f))
log.info('Locales update successfully...')
return
def main(args):
if args.update:
_update()
return
if args.locales:
_locales(args)
return
if args.embed:
_embed(args)
return
@ -469,6 +525,10 @@ def _process_command_line_arguments():
default=False, required=False)
parser.add_argument('-d', '--document', dest='document', default='')
parser.add_argument('-f', '--files', dest='files', default='')
parser.add_argument('-l', '--locales', dest='locales', action='store_true',
default=False, required=False)
parser.add_argument('-u', '--update', dest='update', action='store_true',
default=False, required=False)
return parser.parse_args()