Refactory

This commit is contained in:
Mauricio Baeza 2022-08-15 23:57:31 -05:00
parent cf05ff1cf1
commit 4812a8d14f
19 changed files with 2836 additions and 14686 deletions

View File

@ -0,0 +1,10 @@
+++
title = "LibreOffice"
weight = 4
+++
### create_instance
```python
```

View File

@ -0,0 +1,12 @@
+++
title = "Calc"
weight = 5
+++
#### Trabajar con Calc
### active
```python
```

View File

@ -0,0 +1,76 @@
+++
title = "Cuadros de diálogo"
weight = 6
+++
#### Trabajar con cuadros de diálogo
### create
##### Desde archivo
Crear un cuadro de diálogo desde un archivo `xdl` previamente creado desde el editor de cuadros de diálogo dentro de LibreOffice y exportado a un archivo.
```python
def crear_cuadro_de_dialogo():
path = '/home/mau/Desktop/Dialog1.xdl'
propiedades = {'Path': path}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
##### Desde mis macros
Si el cuadro de diálogo esta en la librería `Standard`.
```python
def crear_cuadro_de_dialogo():
propiedades = {
'Location': 'user',
'Name': 'Dialog1',
}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
Si el cuadro de diálogo esta en otra librería.
```python
def crear_cuadro_de_dialogo():
propiedades = {
'Location': 'user',
'Library': 'MiAplicacion',
'Name': 'Dialog2',
}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
Si el cuadro de diálogo esta en el documento activo en la librería `Standard`.
```python
def crear_cuadro_de_dialogo():
propiedades = {
'Location': 'document',
'Name': 'miApp',
}
dialog = app.dialog.create(propiedades)
dialog.open()
return
```
##### Crear dinámicamente
Crear un cuadro de diálogo vacío.
```python
def crear_cuadro_de_dialogo():
dialog = app.dialog.create()
dialog.open()
return
```

View File

@ -0,0 +1,105 @@
+++
title = "Herramientas"
weight = 3
+++
Recuerda, es necesario importar la librería.
```python
import easymacro as app
```
#### Información sobre la PC
### OS
Obtener el sistema operativo.
```python
app.msgbox(app.OS)
```
### DESKTOP
Obtener el tipo de escritorio, solo en GNU/Linux.
```python
app.msgbox(app.DESKTOP)
```
### PC
Obtener el nombre de la computadora.
```python
app.msgbox(app.PC)
```
### USER
Obtener el nombre de usuario.
```python
app.msgbox(app.USER)
```
### IS_WIN
Saber si estamos en Windows.
```python
app.msgbox(app.IS_WIN)
```
### IS_MAC
Saber si estamos en OSX.
```python
app.msgbox(app.IS_MAC)
```
#### Información sobre LibreOffice
### NAME
Nombre de la aplicación.
```python
app.msgbox(app.NAME)
```
### VERSION
Versión de la aplicación.
```python
app.msgbox(app.VERSION)
```
### LANG
Lenguaje de la aplicación.
```python
app.msgbox(app.LANG)
```
### LANGUAGE
Lenguaje con variante.
```python
app.msgbox(app.LANGUAGE)
```
[1]: https://git.cuates.net/elmau/easymacro/issues

View File

@ -0,0 +1,153 @@
+++
title = "Fechas y tiempo"
weight = 2
+++
{{% notice tip %}}
La fecha inicial en Calc y en Python es diferente.
{{% /notice %}}
### today
Obtener la fecha de hoy.
```python
d = app.dates
app.msgbox(d.today)
```
### now
Obtener la fecha y hora actuales.
```python
d = app.dates
app.msgbox(d.now)
```
### time
Obtener la hora actual.
```python
d = app.dates
app.msgbox(d.now.time())
```
### epoch
Obtener el [tiempo Unix][1]
```python
d = app.dates
app.msgbox(d.epoch)
```
### date
Devolver una fecha
```python
d = app.dates
date = d.date(1974, 1, 15)
app.msgbox(date)
```
### time
Devolver un tiempo
```python
d = app.dates
time = d.time(10, 20, 15)
app.msgbox(time)
```
### datetime
Devolver fecha y hora
```python
d = app.dates
dt = d.datetime(1974, 1, 15, 10, 11, 12)
app.msgbox(dt)
```
### str_to_date
Convertir una cadena en fecha. Mira este [excelente recurso][2]
```python
d = app.dates
cadena = '1974-01-15'
plantilla = '%Y-%m-%d'
fecha = d.str_to_date(cadena, plantilla)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
Para obtener un valor válido para establecer en una celda de Calc.
```python
d = app.dates
cadena = '1974-01-15'
plantilla = '%Y-%m-%d'
fecha = d.str_to_date(cadena, plantilla, True)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
### calc_to_date
Convierte el valor de una celda en una fecha Python, por ejemplo, la fecha inicial configurada en Calc.
```python
d = app.dates
value_from_cell = 1
fecha = d.calc_to_date(value_from_cell)
app.msgbox(fecha)
app.msgbox(type(fecha))
```
### start y end
Medir tiempo en segundos.
```python
d = app.dates
d.start()
app.sleep(5)
seconds = d.end()
app.msgbox(seconds)
```
Regresar timedelta en vez de segundos.
```python
d = app.dates
d.start()
app.sleep(5)
td = d.end(False)
app.msgbox(td)
```
[1]: https://en.wikipedia.org/wiki/Unix_time
[2]: https://strftime.org

View File

@ -0,0 +1,18 @@
+++
title = "Correo electrónico"
weight = 3
+++
#### Enviar correo electrónico.
{{% notice tip %}}
Siempre guarda las contraseñas de la forma más segura posible.
{{% /notice %}}
### send
Enviar un correo electrónico.
```python
```

View File

@ -0,0 +1,69 @@
+++
title = "Mensajes"
weight = 1
+++
#### Cuadros de mensaje
### msgbox
Mostrar mensaje estandar.
```python
mensaje = 'Maldito Mundo'
titulo = 'Mi Macro'
app.msgbox(mensaje, titulo)
```
### warning
Mostrar mensaje con icono de advertencia.
```python
mensaje = 'Cuidado, esta acción es peligrosa'
titulo = 'Mi Macro'
app.warning(mensaje, titulo)
```
### errorbox
Mostrar mensaje con icono de error.
```python
mensaje = 'ERROR: contacte a soporte'
titulo = 'Mi Macro'
app.errorbox(mensaje, titulo)
```
### question
Hacer una pregunta mostrando el icono de interrogación y mostrando los botones de comando `Si` y `No`. La respuesta siempre es verdadera (`True`) si el usuario selecciona `si` y falsa (`False`) en caso contrario.
```python
mensaje = '¿Es fácil Python?'
titulo = 'Mi Macro'
resultado = app.question(mensaje, titulo)
app.msgbox(resultado)
```
### inputbox
Muestra un mensaje al usuario, permitiendo capturar una respuesta.
```python
mensaje = 'Escribe tu nombre'
nombre = app.inputbox(mensaje)
app.msgbox(nombre)
```
Para ocultar solo en pantalla lo que captura el usuario, como contraseñas.
```python
mensaje = 'Captura la contraseña'
echochar = '*'
contraseña = app.inputbox(mensaje, echochar=echochar)
app.msgbox(contraseña)
```

View File

@ -0,0 +1,569 @@
+++
title = "Rutas y archivos"
weight = 2
+++
#### Trabajar con rutas y archivos.
### path
Obtener información de una ruta.
```python
ruta_archivo = '/home/mau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.path)
app.debug(p.file_name)
app.debug(p.name)
app.debug(p.ext)
app.debug(p.size)
app.debug(p.url)
```
```
15/08/2022 14:40:08 - DEBUG - /home/mau
15/08/2022 14:40:08 - DEBUG - mi_archivo.ods
15/08/2022 14:40:08 - DEBUG - mi_archivo
15/08/2022 14:40:08 - DEBUG - ods
15/08/2022 14:40:08 - DEBUG - 7011
15/08/2022 14:40:08 - DEBUG - file:///home/mau/mi_archivo.ods
```
Obtener la misma información como un tupla.
```python
ruta_archivo = '/home/mau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.info)
```
```
15/08/2022 14:43:01 - DEBUG - ('/home/mau', 'mi_archivo.ods', 'mi_archivo', 'ods', 7011, 'file:///home/mau/mi_archivo.ods')
```
O como diccionario.
```python
ruta_archivo = '/home/mau/mi_archivo.ods'
p = app.paths(ruta_archivo)
app.debug(p.dict)
```
```
15/08/2022 14:43:01 - DEBUG - {'path': '/home/mau', 'file_name': 'mi_archivo.ods', 'name': 'mi_archivo', 'ext': 'ods', 'size': 7011, 'url': 'file:///home/mau/mi_archivo.ods'}
```
### home
Obtener la carpeta de inicio del usuario.
```python
p = app.paths
app.debug(p.home)
```
### documents
Obtener la carpeta Documentos del usuario.
```python
p = app.paths
app.debug(p.documents)
```
### user_profile
Obtener la ruta del perfil de usuario.
```python
p = app.paths
app.debug(p.user_profile)
```
### user_config
Obtener la ruta de la carpeta `config` en el perfil de usuario.
```python
p = app.paths
app.debug(p.user_config)
```
### python
Obtener la ruta del ejecutable `python`
```python
p = app.paths
app.debug(p.python)
```
### to_system
Pasar una ruta en formato URL al formato del sistema de archivos del SO.
```python
p = app.paths
ruta_url = 'file:///home/mau/mi_archivo.ods'
ruta = p.to_system(ruta_url)
app.debug(ruta)
```
### to_url
Pasar una ruta del sistema de archivos del SO al formato URL.
```python
p = app.paths
ruta = '/home/mau/mi_archivo.ods'
ruta_url = p.to_url(ruta)
app.debug(ruta_url)
```
### config
Obtener rutas de la configuración de LibreOffice. Por default obtiene la ruta de `Documentos`, para otras ruta mire [Api XPathSettings][1]
```python
p = app.paths
ruta = p.config()
app.debug(ruta)
ruta = p.config('UserConfig')
app.debug(ruta)
```
{{% notice tip %}}
Algunas rutas pueden ser más de una, separados por `;`, en este caso, el resultado es una lista con las rutas.
{{% /notice %}}
### join
Concatenar rutas.
```python
p = app.paths
ruta = p.join('/home/mau', 'pruebas', 'archivo.ods')
app.debug(ruta)
```
### exists
Verificar si una ruta existe.
```python
p = app.paths
resultado = p.exists('/home/mau/test/archivo.ods')
app.debug(resultado)
```
### exists_app
Verificar si una aplicación existe.
```python
p = app.paths
resultado = p.exists_app('noexiste')
app.debug(resultado)
resultado = p.exists_app('soffice')
app.debug(resultado)
```
### is_dir
Verificar si la ruta es un directorio.
```python
p = app.paths
resultado = p.is_dir('/home/mau')
app.debug(resultado)
```
### is_file
Verificar si la ruta es un archivo.
```python
p = app.paths
resultado = p.is_file('/home/mau/mi_archivo.ods')
app.debug(resultado)
```
### temp_file
Crear un archivo temporal, es borrado automáticamente al cerrarse.
```python
p = app.paths
f = p.temp_file()
f.write(app.INFO_DEBUG)
f.close()
```
Usado en `contexto`, se cierra automáticamente.
```python
with p.temp_file() as f:
app.debug(f.name)
f.write('test')
```
### temp_dir
Crear un directorio temporal, al salir del contexto, es eliminado junto con todo su contenido del sistema de archivos.
```python
p = app.paths
with p.temp_dir() as d:
app.debug(p.exists(d))
app.debug(d)
app.debug(p.exists(d))
```
### get
Permitir al usuario seleccionar archivos, devuelve solo la ruta. De forma predeterminada abre en la carpeta `Documentos`.
```python
p = app.paths
ruta = p.get()
app.debug(ruta)
```
Establecer que abra en otro directorio.
```python
ruta = p.get('/tmp')
app.debug(ruta)
```
Agregar un filtro.
```python
ruta = p.get(filters='ods')
app.debug(ruta)
```
Agregar multiples filtros.
```python
ruta = p.get(filters='xml,txt')
app.debug(ruta)
```
Permitir selecciones multiples.
```python
ruta = p.get(filters='xml,txt', multiple=True)
app.debug(ruta)
```
### get_dir
Permitir al usuario seleccionar un directorio, devuelve solo la ruta. De forma predeterminada abre en la carpeta `Documentos`.
```python
p = app.paths
ruta = p.get_dir()
app.debug(ruta)
```
Establecer que abra en otro directorio.
```python
ruta = p.get_dir('/tmp')
app.debug(ruta)
```
### get_for_save
Permitir seleccionar un directorio y capturar el nombre del archivo, devuelve la ruta completa.
```python
p = app.paths
ruta = p.get_for_save()
app.debug(ruta)
```
Establecer que inicie en otro directorio.
```python
ruta = p.get_for_save('/tmp')
app.debug(ruta)
```
Si se establece un filtro, automáticamente se agrega la extensión.
```python
ruta = p.get_for_save(filters='txt')
app.debug(ruta)
```
### files
Obtener archivos de una ruta, no recursivamente. De forma predeterminada regresa todos, incluyendo archivos ocultos.
```python
ruta = '/home/mau'
p = app.paths
archivos = p.files(ruta)
for a in archivos:
app.debug(a)
```
Filtrar por tipo de archivo.
```python
p = app.paths
archivos = p.files(ruta, '*.pdf')
```
Obtener archivos de forma recursiva.
```python
p = app.paths
archivos = p.files(ruta, '**/*.xml')
```
### walk
Obtener archivos de forma recursiva.
```python
p = app.paths
ruta = '/home/mau/Documents'
archivos = p.walk(ruta)
for a in archivos:
app.debug(a)
```
Con filtro.
```python
archivos = p.walk(ruta, 'ods')
```
Con filtros.
```python
archivos = p.walk(ruta, 'ods|odt')
```
### dirs
Obtener los directorios de una ruta, no recursivamente.
```python
p = app.paths
ruta = '/home/mau/Documents'
folders = p.dirs(ruta)
for f in folders:
app.debug(f)
```
### walk_dirs
Obtener los directorios de una ruta, no recursivamente.
```python
p = app.paths
ruta = '/home/mau/Documents'
folders = p.walk_dirs(ruta)
for f in folders:
app.debug(f)
```
Obtener información en una lista de tuplas: (ID_FOLDER, ID_PADRE, NOMBRE)
```python
folders = p.walk_dirs(ruta, True)
```
### extension
Obtener la ruta de instalación de una extensión a partir de su ID.
```python
p = app.paths
id_ext = 'net.elmau.zaz.talk'
ruta = p.extension(id_ext)
app.debug(ruta)
```
### replace_ext
Reemplazar extensión de un archivo.
```python
p = app.paths
ruta = '/home/mau/mi_archivo.ods'
ruta_nueva = p.replace_ext(ruta, 'pdf')
app.debug(ruta_nueva)
```
### open
Abrir cualquier archivo con el programas predeterminado del SO.
```python
p = app.paths
ruta = '/home/mau/archivo.pdf'
p.open(ruta)
ruta = '/home/mau/index.html'
p.open(ruta)
```
### save y read
Guardar y leer datos, el encoding predeterminado es UTF8.
```python
p = app.paths
datos = """¿Quieres saber quién eres? No preguntes. Actúa.
La acción te delineará y definirá.
Thomas Jefferson
"""
ruta = '/home/mau/temp.txt'
p.save(ruta, datos)
datos = p.read(ruta)
app.msgbox(datos)
```
Cambiar el encoding.
```python
app.paths.save(ruta, datos, 'iso-8859-1')
```
### save_bin y read_bin
Guardar y leer datos binarios.
```python
p = app.paths
datos = b'Datos binarios'
ruta = '/home/mau/temp.bin'
p.save_bin(ruta, datos)
datos = p.read_bin(ruta)
app.msgbox(datos)
```
### save_json y read_json
Guardar y leer en formato json.
```python
p = app.paths
ruta = '/home/mau/datos.json'
datos = {
'tipo': 'calc',
'nombre': 'miarchivo.ods',
}
p.save_json(ruta, datos)
datos = p.read_json(ruta)
app.msgbox(datos)
```
### save_csv y read_csv
Exportar e importar datos en formato CSV. Vea la documentación [CSV][2] para los argumentos que puede usar.
```python
p = app.paths
ruta = '/home/mau/datos.csv'
ahora = app.dates.now
datos = (
(1, 'uno', ahora),
(2, 'dos', ahora),
(3, 'tres', ahora),
)
p.save_csv(ruta, datos)
datos = p.read_csv(ruta)
app.msgbox(datos)
```
### kill
Borra archivos o directorios con todo su contenido. Devuelve verdadero (True) en caso de exito y falso (Falso) en cualquier otro caso.
{{% notice warning %}}
Este proceso es destructivo, es buena practica siempre solicitar confirmación al usuario.
{{% /notice %}}
```python
p = app.paths
ruta = '/home/mau/temp.bin'
resultado = p.kill(ruta)
app.msgbox(resultado)
```
### copy
Copiar archivos. Devuelve la ruta completa final destino.
De un origen a una carpeta destino
```python
p = app.paths
ruta_origen = '/home/mau/temp.txt'
ruta_destino = '/home/mau/Desktop'
ruta = p.copy(ruta_origen, ruta_destino)
app.debug(ruta)
```
Cambiar el nombre destino.
```python
ruta_origen = '/home/mau/temp.txt'
ruta_destino = '/home/mau/Desktop'
nuevo_nombre = 'datos.csv'
ruta = p.copy(ruta_origen, ruta_destino, nuevo_nombre)
app.debug(ruta)
```
[1]: http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1util_1_1XPathSettings.html
[2]: https://docs.python.org/3.7/library/csv.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
from .easymain import *
from .easydialog import *
from .easytools import *
from .easydocs import LODocuments
@ -8,7 +9,11 @@ from .easydocs import LODocuments
def __getattr__(name):
classes = {
'active': LODocuments().active,
'inspect': LOInspect
'dates': Dates,
'dialog': LODialog,
'email': Email,
'inspect': LOInspect,
'paths': Paths,
}
if name in classes:

View File

@ -0,0 +1,741 @@
#!/usr/bin/env python3
from typing import Any
from com.sun.star.view.SelectionType import SINGLE, MULTI, RANGE
from .easyevents import *
from .easydocs import LODocuments
from .easymain import log, TITLE, create_instance, BaseObject
from .easytools import Paths, Services, LOInspect
from .easytools import _, set_properties
__all__ = [
'LODialog',
'inputbox',
]
SEPARATION = 5
MODELS = {
'button': 'com.sun.star.awt.UnoControlButtonModel',
'label': 'com.sun.star.awt.UnoControlFixedTextModel',
'link': 'com.sun.star.awt.UnoControlFixedHyperlinkModel',
'radio': 'com.sun.star.awt.UnoControlRadioButtonModel',
'checkbox': 'com.sun.star.awt.UnoControlCheckBoxModel',
'text': 'com.sun.star.awt.UnoControlEditModel',
'image': 'com.sun.star.awt.UnoControlImageControlModel',
'listbox': 'com.sun.star.awt.UnoControlListBoxModel',
'roadmap': 'com.sun.star.awt.UnoControlRoadmapModel',
'tree': 'com.sun.star.awt.tree.TreeControlModel',
'grid': 'com.sun.star.awt.grid.UnoControlGridModel',
'pages': 'com.sun.star.awt.UnoMultiPageModel',
'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel',
'combobox': 'com.sun.star.awt.UnoControlComboBoxModel',
'spinbutton': 'com.sun.star.awt.UnoControlSpinButtonModel',
'numeric': 'com.sun.star.awt.UnoControlNumericFieldModel',
}
TYPE_CONTROL = {
'stardiv.Toolkit.UnoFixedTextControl': 'label',
'stardiv.Toolkit.UnoEditControl': 'text',
'stardiv.Toolkit.UnoButtonControl': 'button',
}
IMPLEMENTATIONS = {
'grid': 'stardiv.Toolkit.GridControl',
'link': 'stardiv.Toolkit.UnoFixedHyperlinkControl',
'roadmap': 'stardiv.Toolkit.UnoRoadmapControl',
'pages': 'stardiv.Toolkit.UnoMultiPageControl',
}
def add_listeners(events, control):
name = control.Model.Name
listeners = {
'addActionListener': EventsButton,
# ~ 'addMouseListener': EventsMouse,
# ~ 'addFocusListener': EventsFocus,
# ~ 'addItemListener': EventsItem,
# ~ 'addKeyListener': EventsKey,
# ~ 'addTabListener': EventsTab,
# ~ 'addSpinListener': EventsSpin,
}
if hasattr(control, 'obj'):
control = control.obj
# ~ log.debug(control.ImplementationName)
is_grid = control.ImplementationName == IMPLEMENTATIONS['grid']
is_link = control.ImplementationName == IMPLEMENTATIONS['link']
is_roadmap = control.ImplementationName == IMPLEMENTATIONS['roadmap']
is_pages = control.ImplementationName == IMPLEMENTATIONS['pages']
for key, value in listeners.items():
if hasattr(control, key):
if is_grid and key == 'addMouseListener':
control.addMouseListener(EventsMouseGrid(events, name))
continue
if is_link and key == 'addMouseListener':
control.addMouseListener(EventsMouseLink(events, name))
continue
if is_roadmap and key == 'addItemListener':
control.addItemListener(EventsItemRoadmap(events, name))
continue
getattr(control, key)(listeners[key](events, name))
if is_grid:
controllers = EventsGrid(events, name)
control.addSelectionListener(controllers)
control.Model.GridDataModel.addGridDataListener(controllers)
return
class UnoBaseObject(object):
def __init__(self, obj: Any):
self._obj = obj
self._model = obj.Model
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
@property
def obj(self):
return self._obj
@property
def model(self):
return self._model
@property
def m(self):
return self._model
@property
def properties(self):
data = LOInspect(self.obj).properties
return data
@properties.setter
def properties(self, properties: dict):
set_properties(self.model, properties)
@property
def name(self):
return self.model.Name
@property
def parent(self):
return self.obj.Context
@property
def tag(self):
return self.model.Tag
@tag.setter
def tag(self, value):
self.model.Tag = value
@property
def visible(self):
return self.obj.Visible
@visible.setter
def visible(self, value):
self.obj.setVisible(value)
@property
def enabled(self):
return self.model.Enabled
@enabled.setter
def enabled(self, value):
self.model.Enabled = value
@property
def step(self):
return self.model.Step
@step.setter
def step(self, value):
self.model.Step = value
@property
def align(self):
return self.model.Align
@align.setter
def align(self, value):
self.model.Align = value
@property
def valign(self):
return self.model.VerticalAlign
@valign.setter
def valign(self, value):
self.model.VerticalAlign = value
@property
def font_weight(self):
return self.model.FontWeight
@font_weight.setter
def font_weight(self, value):
self.model.FontWeight = value
@property
def font_height(self):
return self.model.FontHeight
@font_height.setter
def font_height(self, value):
self.model.FontHeight = value
@property
def font_name(self):
return self.model.FontName
@font_name.setter
def font_name(self, value):
self.model.FontName = value
@property
def font_underline(self):
return self.model.FontUnderline
@font_underline.setter
def font_underline(self, value):
self.model.FontUnderline = value
@property
def text_color(self):
return self.model.TextColor
@text_color.setter
def text_color(self, value):
self.model.TextColor = value
@property
def back_color(self):
return self.model.BackgroundColor
@back_color.setter
def back_color(self, value):
self.model.BackgroundColor = value
@property
def multi_line(self):
return self.model.MultiLine
@multi_line.setter
def multi_line(self, value):
self.model.MultiLine = value
@property
def help_text(self):
return self.model.HelpText
@help_text.setter
def help_text(self, value):
self.model.HelpText = value
@property
def border(self):
return self.model.Border
@border.setter
def border(self, value):
# ~ Bug for report
self.model.Border = value
@property
def width(self):
return self._model.Width
@width.setter
def width(self, value):
self.model.Width = value
@property
def height(self):
return self.model.Height
@height.setter
def height(self, value):
self.model.Height = value
def _get_possize(self, name):
ps = self.obj.getPosSize()
return getattr(ps, name)
def _set_possize(self, name, value):
ps = self.obj.getPosSize()
setattr(ps, name, value)
self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, POSSIZE)
return
@property
def x(self):
if hasattr(self.model, 'PositionX'):
return self.model.PositionX
return self._get_possize('X')
@x.setter
def x(self, value):
if hasattr(self.model, 'PositionX'):
self.model.PositionX = value
else:
self._set_possize('X', value)
@property
def y(self):
if hasattr(self.model, 'PositionY'):
return self.model.PositionY
return self._get_possize('Y')
@y.setter
def y(self, value):
if hasattr(self.model, 'PositionY'):
self.model.PositionY = value
else:
self._set_possize('Y', value)
@property
def tab_index(self):
return self._model.TabIndex
@tab_index.setter
def tab_index(self, value):
self.model.TabIndex = value
@property
def tab_stop(self):
return self._model.Tabstop
@tab_stop.setter
def tab_stop(self, value):
self.model.Tabstop = value
@property
def ps(self):
ps = self.obj.getPosSize()
return ps
@ps.setter
def ps(self, ps):
self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, POSSIZE)
def set_focus(self):
self.obj.setFocus()
return
def ps_from(self, source):
self.ps = source.ps
return
def center(self, horizontal=True, vertical=False):
p = self.parent.Model
w = p.Width
h = p.Height
if horizontal:
x = w / 2 - self.width / 2
self.x = x
if vertical:
y = h / 2 - self.height / 2
self.y = y
return
def move(self, origin, x=0, y=5, center=False):
if x:
self.x = origin.x + origin.width + x
else:
self.x = origin.x
if y:
h = origin.height
if y < 0:
h = 0
self.y = origin.y + h + y
else:
self.y = origin.y
if center:
self.center()
return
class UnoLabel(UnoBaseObject):
def __init__(self, obj):
super().__init__(obj)
@property
def type(self):
return 'label'
@property
def value(self):
return self.model.Label
@value.setter
def value(self, value):
self.model.Label = value
# ~ https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1awt_1_1UnoControlEditModel.html
class UnoText(UnoBaseObject):
def __init__(self, obj):
super().__init__(obj)
@property
def type(self):
return 'text'
@property
def value(self):
return self.model.Text
@value.setter
def value(self, value):
self.model.Text = value
@property
def echochar(self):
return chr(self.model.EchoChar)
@echochar.setter
def echochar(self, value):
if value:
self.model.EchoChar = ord(value[0])
else:
self.model.EchoChar = 0
def validate(self):
return
class UnoButton(UnoBaseObject):
def __init__(self, obj):
super().__init__(obj)
@property
def type(self):
return 'button'
@property
def value(self):
return self.model.Label
@value.setter
def value(self, value):
self.model.Label = value
@property
def image(self):
return self.model.ImageURL
@image.setter
def image(self, value):
self.model.ImageURL = Paths.to_url(value)
UNO_CLASSES = {
'label': UnoLabel,
'text': UnoText,
'button': UnoButton,
# ~ 'link': UnoLabelLink,
# ~ 'radio': UnoRadio,
# ~ 'checkbox': UnoCheckBox,
# ~ 'image': UnoImage,
# ~ 'listbox': UnoListBox,
# ~ 'roadmap': UnoRoadmap,
# ~ 'tree': UnoTree,
# ~ 'grid': UnoGrid,
# ~ 'pages': UnoPages,
# ~ 'spinbutton': UnoSpinButton,
# ~ 'numeric': UnoNumericField,
}
class DialogBox(BaseObject):
SERVICE = 'com.sun.star.awt.DialogProvider'
SERVICE_DIALOG = 'com.sun.star.awt.UnoControlDialog'
def __init__(self, properties: dict={}):
self._controls = {}
obj = self._create(properties)
super().__init__(obj)
self._init_controls()
def _create_from_path(self, path: str):
dp = create_instance(self.SERVICE, True)
dialog = dp.createDialog(Paths.to_url(path))
return dialog
def _create_from_location(self, properties: dict):
# ~ uid = docs.active.uid
# ~ url = f'vnd.sun.star.tdoc:/{uid}/Dialogs/{library}/{name}.xml'
name = properties['Name']
library = properties.get('Library', 'Standard')
location = properties.get('Location', 'application').lower()
if location == 'user':
location = 'application'
url = f'vnd.sun.star.script:{library}.{name}?location={location}'
if location == 'document':
doc = LODocuments().active.obj
dp = create_instance(self.SERVICE, arguments=doc)
else:
dp = create_instance(self.SERVICE, True)
dialog = dp.createDialog(url)
return dialog
def _create_from_properties(self, properties: dict):
dialog = create_instance(self.SERVICE_DIALOG, True)
model = create_instance(f'{self.SERVICE_DIALOG}Model', True)
properties['Width'] = properties.get('Width', 200)
properties['Height'] = properties.get('Height', 150)
set_properties(model, properties)
dialog.setModel(model)
dialog.setVisible(False)
dialog.createPeer(Services.toolkit, None)
return dialog
def _create(self, properties: dict):
path = properties.pop('Path', '')
if path:
dialog = self._create_from_path(path)
elif 'Location' in properties:
dialog = self._create_from_location(properties)
else:
dialog = self._create_from_properties(properties)
return dialog
def _init_controls(self):
for control in self.obj.Controls:
tipo = control.ImplementationName
name = control.Model.Name
if not tipo in TYPE_CONTROL:
log.debug(f'Type control: {tipo}')
raise AttributeError(f"Has no class '{tipo}'")
control = UNO_CLASSES[TYPE_CONTROL[tipo]](control)
setattr(self, name, control)
self._controls[name] = control
return
def execute(self):
return self.obj.execute()
def open(self):
return self.execute()
def close(self, value=0):
value = self.obj.endDialog(value)
return value
# ~ def close(self, value=0):
# ~ if self._modal:
# ~ value = self.obj.endDialog(value)
# ~ else:
# ~ self.visible = False
# ~ self.obj.dispose()
# ~ return value
# ~ def show(self, modal=True):
# ~ self._modal = modal
# ~ if modal:
# ~ return self.obj.execute()
# ~ else:
# ~ self.visible = True
# ~ return
@property
def model(self):
return self.obj.Model
@property
def name(self):
return self.model.Name
@property
def height(self):
return self.model.Height
@height.setter
def height(self, value):
self.model.Height = value
@property
def width(self):
return self.model.Width
@width.setter
def width(self, value):
self.model.Width = value
@property
def visible(self):
return self.obj.Visible
@visible.setter
def visible(self, value):
self.obj.Visible = value
@property
def step(self):
return self.model.Step
@step.setter
def step(self, value):
self.model.Step = value
@property
def color_on_focus(self):
return self._color_on_focus
@color_on_focus.setter
def color_on_focus(self, value):
self._color_on_focus = get_color(value)
@property
def events(self):
return self._events
@events.setter
def events(self, controllers):
self._events = controllers(self)
self._connect_listeners()
def _connect_listeners(self):
for control in self.obj.Controls:
add_listeners(self.events, control)
return
def _set_image_url(self, image: str):
if Paths.exists(image):
return Paths.to_url(image)
path = Paths.join(self._path, DIR['images'], image)
return Paths.to_url(path)
def _special_properties(self, tipo, properties):
if tipo == 'link' and not 'Label' in properties:
properties['Label'] = properties['URL']
return properties
if tipo == 'button':
if 'ImageURL' in properties:
properties['ImageURL'] = self._set_image_url(properties['ImageURL'])
properties['FocusOnClick'] = properties.get('FocusOnClick', False)
return properties
if tipo == 'roadmap':
properties['Height'] = properties.get('Height', self.height)
if 'Title' in properties:
properties['Text'] = properties.pop('Title')
return properties
if tipo == 'tree':
properties['SelectionType'] = properties.get('SelectionType', SINGLE)
return properties
if tipo == 'grid':
properties['X'] = properties.get('X', SEPARATION)
properties['Y'] = properties.get('Y', SEPARATION)
properties['Width'] = properties.get('Width', self.width - SEPARATION * 2)
properties['Height'] = properties.get('Height', self.height - SEPARATION * 2)
properties['ShowRowHeader'] = properties.get('ShowRowHeader', True)
return properties
if tipo == 'pages':
properties['Width'] = properties.get('Width', self.width)
properties['Height'] = properties.get('Height', self.height)
return properties
def add_control(self, properties):
tipo = properties.pop('Type').lower()
root = properties.pop('Root', '')
sheets = properties.pop('Sheets', ())
columns = properties.pop('Columns', ())
properties = self._special_properties(tipo, properties)
model = self.model.createInstance(MODELS[tipo])
set_properties(model, properties)
name = properties['Name']
self.model.insertByName(name, model)
control = self.obj.getControl(name)
add_listeners(self.events, control)
control = UNO_CLASSES[tipo](control)
if tipo in ('listbox',):
control.path = self.path
if tipo == 'tree' and root:
control.root = root
elif tipo == 'grid' and columns:
control.columns = columns
elif tipo == 'pages' and sheets:
control.sheets = sheets
control.events = self.events
setattr(self, name, control)
self._controls[name] = control
return control
class LODialog():
@classmethod
def create(cls, properties: dict={}):
return DialogBox(properties)
def inputbox(message, default='', title=TITLE, echochar=''):
class ControllersInput(object):
def __init__(self, dialog):
self.d = dialog
def cmd_ok_action(self, event):
self.d.close(1)
return
properties = {
'Title': title,
'Width': 200,
'Height': 80,
}
dlg = DialogBox(properties)
dlg.events = ControllersInput
properties = {
'Type': 'Label',
'Name': 'lbl_msg',
'Label': message,
'Width': 140,
'Height': 50,
'X': 5,
'Y': 5,
'MultiLine': True,
'Border': 1,
}
dlg.add_control(properties)
properties = {
'Type': 'Text',
'Name': 'txt_value',
'Text': default,
'Width': 190,
'Height': 15,
}
if echochar:
properties['EchoChar'] = ord(echochar[0])
dlg.add_control(properties)
dlg.txt_value.move(dlg.lbl_msg)
properties = {
'Type': 'button',
'Name': 'cmd_ok',
'Label': _('OK'),
'Width': 40,
'Height': 15,
'DefaultButton': True,
'PushButtonType': 1,
}
dlg.add_control(properties)
dlg.cmd_ok.move(dlg.lbl_msg, 10, 0)
properties = {
'Type': 'button',
'Name': 'cmd_cancel',
'Label': _('Cancel'),
'Width': 40,
'Height': 15,
'PushButtonType': 2,
}
dlg.add_control(properties)
dlg.cmd_cancel.move(dlg.cmd_ok)
value = ''
if dlg.open():
value = dlg.txt_value.value
return value

View File

@ -0,0 +1,40 @@
#!/usr/bin/env python3
import unohelper
from com.sun.star.awt import XActionListener
from com.sun.star.lang import XEventListener
__all__ = [
'EventsButton',
]
class EventsListenerBase(unohelper.Base, XEventListener):
def __init__(self, controller, name, window=None):
self._controller = controller
self._name = name
self._window = window
@property
def name(self):
return self._name
def disposing(self, event):
self._controller = None
if not self._window is None:
self._window.setMenuBar(None)
class EventsButton(EventsListenerBase, XActionListener):
def __init__(self, controller, name):
super().__init__(controller, name)
def actionPerformed(self, event):
event_name = f'{self.name}_action'
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return

View File

@ -57,7 +57,7 @@ logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
log = logging.getLogger(__name__)
def create_instance(name: str, with_context: bool=False, argument: Any=None) -> Any:
def create_instance(name: str, with_context: bool=False, arguments: Any=None) -> Any:
"""Create a service instance
:param name: Name of service
@ -72,8 +72,8 @@ def create_instance(name: str, with_context: bool=False, argument: Any=None) ->
if with_context:
instance = SM.createInstanceWithContext(name, CTX)
elif argument:
instance = SM.createInstanceWithArguments(name, (argument,))
elif arguments:
instance = SM.createInstanceWithArguments(name, (arguments,))
else:
instance = SM.createInstance(name)
@ -155,3 +155,4 @@ class BaseObject():
def obj(self):
"""Return original pyUno object"""
return self._obj

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
#!/usr/bin/env python3
MESSAGES = {
'es': {
'OK': 'Aceptar',
'Cancel': 'Cancelar',
'Select path': 'Seleccionar ruta',
'Select directory': 'Seleccionar directorio',
'Select file': 'Seleccionar archivo',
'Incorrect user or password': 'Nombre de usuario o contraseña inválidos',
'Allow less secure apps in GMail': 'Activa: Permitir aplicaciones menos segura en GMail',
}
}