Add remove, save, clone images

This commit is contained in:
Mauricio 2023-04-24 23:09:03 -06:00
parent 70e1933537
commit b8954d7ade
8 changed files with 505 additions and 51 deletions

View File

@ -106,4 +106,18 @@ Agrega una nueva forma (un rectángulo) y la devuelve.
app.debug(forma)
```
De forma predeterminada la posición será a 1 cm en Y y X y de 3 cm de ancho y alto. Estos valores se pueden modificar al crear la forma. Todas las unidades en milésimas de centímetro.
```py
opciones = dict(
Name = 'mi_rectangulo_1',
Width = 5000,
Height = 2000,
X = 3000,
Y = 1000,
)
forma = formas.add('Rectangle', opciones)
```
<br>

View File

@ -1,7 +1,202 @@
## Propiedades
Todas las unidades en milésimas de centímetro.
---
### **anchor**
Anclaje de la forma, por default se agrega a la página.
#### Anclaje a una celda
```py
celda = hoja['A1']
forma.anchor = celda
```
<br>
### **height**
Alto de la forma.
```py
forma.height = 2000
```
<br>
### **name**
Devuelve o establece el nombre de la forma.
```py
app.debug(forma.name)
forma.name = 'otro_rectangulo'
app.debug(forma.name)
```
<br>
### **obj**
**Solo lectura.** Devuelve el objeto original pyUNO.
```py
objeto = forma.obj
```
<br>
### **possize**
Devuelve o establece la posición y el tamaño de la forma.
```py
posicion_y_tamaño = dict(
Width = 5000,
Height = 2000,
X = 3000,
Y = 1000,
)
forma.possize = posicion_y_tamaño
```
<br>
### **properties**
Devuelve un diccionario con todas las propiedades de la forma.
```py
for p, v in forma.properties.items():
app.debug(f'{p} = {v}')
```
Al establecer solo aplica las que se pasen en un diccionario.
```py
propiedades = dict(
LineColor = app.color('red'),
LineWidth = 100,
)
forma.properties = propiedades
```
!!! tip "Atención"
Aquí hay que usar los nombres "originales" de las propiedades de la forma en el API de LibreOffice.
<br>
### **resize_with_cell**
Si el tamaño de la forma cambia con la celda, solo cuando el anclaje es a una celda.
```py
forma.resize_with_cell = True
```
<br>
### **shape_type**
**Solo lectura**. Devuelve el tipo de forma.
```py
app.debug(forma.shape_type)
```
```
24/04/2023 13:55:32 - DEBUG - com.sun.star.drawing.RectangleShape
```
<br>
### **width**
Ancho de la forma.
```py
forma.width = 6000
```
<br>
### **x**
Posición en el eje X.
```py
forma.x = 5000
```
<br>
### **y**
Posición en el eje Y.
```py
forma.y = 1000
```
## Métodos
---
---
### **clone**
Clona la imagen en la misma hoja.
```py
imagen.clone()
```
Clona la imagen en otra hoja.
```py
imagen.clone(doc['Hoja5'].draw_page)
```
<br>
### **remove**
Eliminar la forma.
```py
forma.remove()
```
<br>
### **save**
Guarda la imagen en disco. Si no se pasa ningún argumento, toma la ruta del documento y el nombre de la imagen.
!!! tip inline end "Atención"
El documento ya debe estar guardado
```py
imagen.save()
```
Podemos pasar una ruta diferente, seguira tomando el nombre de la imagen.
```py
ruta = '/home/elmau/imagenes'
imagen.save(ruta)
```
Podemos cambiar el nombre.
```py
ruta = '/home/elmau/imagenes'
name = f'{hoja.name}_nuevo_nombre'
imagen.save(path, name)
```
<br>

155
doc/docs/examples/index.md Normal file
View File

@ -0,0 +1,155 @@
---
title: Índice
---
# Ejemplos reales de uso
---
## Calc
---
### Solicitar precios
Consultar datos en json a una página web y vaciarlos en una hoja.
=== "EasyMacro"
```py
import easymacro as app
def obtener_precios():
URL = 'https://api.binance.com/api/v3/ticker/price'
respuesta = app.url.get(URL)
if respuesta.status_code == 200:
datos = respuesta.json()
app.active.active['A1'].dict = datos
return
```
=== "Sin EasyMacro"
```py
import uno
import json
from urllib import request
def obtener_precios():
URL = 'https://api.binance.com/api/v3/ticker/price'
data = json.loads(request.urlopen(URL).read().decode())
doc = XSCRIPTCONTEXT.getDocument()
sheet = doc.CurrentController.ActiveSheet
sheet[0,0].String = 'symbol'
sheet[0,1].String = 'price'
for i, row in enumerate(data):
sheet[i + 1,0].String = row['symbol']
sheet[i + 1,1].Value = float(row['price'])
return
```
<br>
### Clonar imagenes
Clonar todas las imagenes de una hoja a otra.
=== "EasyMacro"
```py
doc = app.active
for image in doc[0].dp:
if image.is_image:
image.clone(doc[1].dp)
```
=== "Sin EasyMacro"
```py
import uno
import io
import unohelper
from com.sun.star.io import IOException, XOutputStream
from com.sun.star.beans import PropertyValue
CTX = uno.getComponentContext()
SM = CTX.getServiceManager()
class LOShape():
def __init__(self, shape):
self._shape = shape
class OutputStream(unohelper.Base, XOutputStream):
def __init__(self):
self._buffer = b''
self.closed = 0
@property
def buffer(self):
return self._buffer
def closeOutput(self):
self.closed = 1
def writeBytes(self, seq):
if seq.value:
self._buffer = seq.value
def flush(self):
pass
def clone_image(self, doc, to_sheet):
stream = self._shape.GraphicStream
buffer = self.OutputStream()
size, data = stream.readBytes(buffer, stream.available())
stream = SM.createInstanceWithContext('com.sun.star.io.SequenceInputStream', CTX)
stream.initialize((data,))
image = doc.createInstance('com.sun.star.drawing.GraphicObjectShape')
gp = SM.createInstance('com.sun.star.graphic.GraphicProvider')
properties = (PropertyValue(Name='InputStream', Value=stream),)
image.Graphic = gp.queryGraphic(properties)
to_sheet.DrawPage.add(image)
image.Size = self._shape.Size
image.Position = self._shape.Position
return
def clone_shape(self, doc, to_sheet):
for p in self._shape.CustomShapeGeometry:
if p.Name == 'Type':
type_shape = p.Value.title()
service = f'com.sun.star.drawing.{type_shape}Shape'
shape = doc.createInstance(service)
shape.Size = self._shape.Size
shape.Position = self._shape.Position
to_sheet.DrawPage.add(shape)
return
def main():
IMAGE = 'com.sun.star.drawing.GraphicObjectShape'
SHAPE = 'com.sun.star.drawing.CustomShape'
doc = XSCRIPTCONTEXT.getDocument()
source = doc.CurrentController.ActiveSheet
target = doc.Sheets[1]
for shape in source.DrawPage:
s = LOShape(shape)
if shape.ShapeType == IMAGE:
s.clone_image(doc, target)
elif shape.ShapeType == SHAPE:
s.clone_shape(doc, tar
```
<br>

View File

@ -32,6 +32,8 @@ nav:
- Página de dibujo:
- dp/drawpage.md
- Formas: dp/shapes.md
- Ejemplos de uso:
- examples/index.md
theme:
name: material
locale: es
@ -53,7 +55,8 @@ markdown_extensions:
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
#~ extra:
#~ alternate:
#~ - name: Español

View File

@ -1,51 +1,11 @@
#!/usr/bin/env python3
import uno
import unohelper
from com.sun.star.io import IOException, XOutputStream
from .easymain import (log,
BaseObject, LOMain, Paths,
dict_to_property, create_instance
)
class IOStream(object):
"""Classe for input/output stream"""
class OutputStream(unohelper.Base, XOutputStream):
def __init__(self):
self._buffer = b''
self.closed = 0
@property
def buffer(self):
return self._buffer
def closeOutput(self):
self.closed = 1
def writeBytes(self, seq):
if seq.value:
self._buffer = seq.value
def flush(self):
pass
@classmethod
def buffer(cls):
return io.BytesIO()
@classmethod
def input(cls, buffer):
service = 'com.sun.star.io.SequenceInputStream'
stream = create_instance(service, True)
stream.initialize((uno.ByteSequence(buffer.getvalue()),))
return stream
@classmethod
def output(cls):
return cls.OutputStream()
from .easyuno import IOStream
class LODocument(BaseObject):

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3
from pathlib import Path
from com.sun.star.awt import Size, Point
from .easymain import (
@ -228,7 +229,7 @@ class LODrawPage(BaseObject):
image = self._create_instance('com.sun.star.drawing.GraphicObjectShape')
if isinstance(path, str):
image.GraphicURL = _P.to_url(path)
image.GraphicURL = Path(path).as_uri()
else:
gp = create_instance('com.sun.star.graphic.GraphicProvider')
stream = IOStream.input(path)

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python3
from com.sun.star.awt import Size, Point
from .easymain import BaseObject, set_properties
from .easymain import BaseObject, Paths, create_instance, dict_to_property, set_properties
from .easyuno import IOStream, get_input_stream
class LOShapes(object):
@ -43,6 +44,10 @@ class LOShapes(object):
class LOShape(BaseObject):
IMAGE = 'com.sun.star.drawing.GraphicObjectShape'
MIME_TYPE = {
'image/png': 'png',
'image/jpeg': 'jpg',
}
def __init__(self, obj):
self._obj = obj
@ -52,10 +57,12 @@ class LOShape(BaseObject):
@property
def obj(self):
"""Get original UNO object"""
return self._obj
@property
def anchor(self):
"""Get anchor object"""
return self.obj.Anchor
@anchor.setter
def anchor(self, obj):
@ -66,6 +73,7 @@ class LOShape(BaseObject):
@property
def resize_with_cell(self):
"""If resize with cell"""
return self.obj.ResizeWithCell
@resize_with_cell.setter
def resize_with_cell(self, value):
@ -74,8 +82,7 @@ class LOShape(BaseObject):
@property
def properties(self):
# ~ properties = self.obj.PropertySetInfo.Properties
# ~ data = {p.Name: getattr(self.obj, p.Name) for p in properties}
"""Get all properties"""
data = self.obj.PropertySetInfo.Properties
keys = [p.Name for p in data]
values = self.obj.getPropertyValues(keys)
@ -87,10 +94,12 @@ class LOShape(BaseObject):
@property
def shape_type(self):
"""Get type shape"""
return self.obj.ShapeType
@property
def name(self):
"""Get name"""
return self.obj.Name
@name.setter
def name(self, value):
@ -114,6 +123,7 @@ class LOShape(BaseObject):
@property
def width(self):
"""Width of shape"""
s = self.obj.Size
return s.Width
@width.setter
@ -124,6 +134,7 @@ class LOShape(BaseObject):
@property
def height(self):
"""Height of shape"""
s = self.obj.Size
return s.Height
@height.setter
@ -137,6 +148,7 @@ class LOShape(BaseObject):
return self.obj.Position
@property
def x(self):
"""Position X"""
return self.position.X
@x.setter
def x(self, value):
@ -144,6 +156,7 @@ class LOShape(BaseObject):
@property
def y(self):
"""Position Y"""
return self.position.Y
@y.setter
def y(self, value):
@ -199,11 +212,69 @@ class LOShape(BaseObject):
self.obj.LayerID = value
@property
def is_range(self):
return False
def type(self):
mt = self.obj.GraphicURL.MimeType
mime_type = self.MIME_TYPE.get(mt, mt)
return mime_type
# ~ not work
@property
def visible(self):
return self.obj.Visible
@visible.setter
def visible(self, value):
self.obj.Visible = value
@property
def is_cell(self):
return False
def doc(self):
return self.obj.Parent.Forms.Parent
def remove(self):
"""Auto remove"""
self.obj.Parent.remove(self.obj)
return
def save(self, path: str='', name: str=''):
"""Save image"""
if not path:
path = Paths(self.doc.URL).path
if not name:
name = self.name.replace(' ', '_')
path_img = Paths.join(path, f'{name}.{self.type}')
data = IOStream.to_bin(self.obj.GraphicStream)
Paths.save_bin(path_img, data)
return path_img
def _get_graphic(self):
stream = self.obj.GraphicStream
buffer = IOStream.output()
_, data = stream.readBytes(buffer, stream.available())
stream = get_input_stream(data)
gp = create_instance('com.sun.star.graphic.GraphicProvider')
properties = dict_to_property({'InputStream': stream})
graphic = gp.queryGraphic(properties)
return graphic
def clone(self, draw_page=None):
"""Clone image"""
image = self.doc.createInstance('com.sun.star.drawing.GraphicObjectShape')
image.Graphic = self._get_graphic()
plus = 0
if draw_page is None:
draw_page = self.obj.Parent
plus = 1000
else:
if hasattr(draw_page, 'obj'):
draw_page = draw_page.obj
draw_page.add(image)
image.Size = self.size
position = self.position
position.X += plus
position.Y += plus
image.Position = position
return LOShape(image)

View File

@ -1,5 +1,9 @@
#!/usr/bin/env python3
import unohelper
from com.sun.star.io import IOException, XOutputStream
from .easymain import create_instance
# UNO Enum
class MessageBoxType():
@ -9,3 +13,54 @@ class MessageBoxType():
"""
from com.sun.star.awt.MessageBoxType \
import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
class IOStream(object):
"""Classe for input/output stream"""
class OutputStream(unohelper.Base, XOutputStream):
def __init__(self):
self._buffer = b''
self.closed = 0
@property
def buffer(self):
return self._buffer
def closeOutput(self):
self.closed = 1
def writeBytes(self, seq):
if seq.value:
self._buffer = seq.value
def flush(self):
pass
@classmethod
def buffer(cls):
return io.BytesIO()
@classmethod
def input(cls, buffer):
service = 'com.sun.star.io.SequenceInputStream'
stream = create_instance(service, True)
stream.initialize((uno.ByteSequence(buffer.getvalue()),))
return stream
@classmethod
def output(cls):
return cls.OutputStream()
@classmethod
def to_bin(cls, stream):
buffer = cls.OutputStream()
_, data = stream.readBytes(buffer, stream.available())
return data.value
def get_input_stream(data):
stream = create_instance('com.sun.star.io.SequenceInputStream', True)
stream.initialize((data,))
return stream