Merge branch 'develop'

Add DrawPage
Add access sheets by code name
This commit is contained in:
el Mau 2022-09-23 12:56:30 -05:00
commit 0ff38cf55f
8 changed files with 480 additions and 16 deletions

View File

@ -1,3 +1,7 @@
v 0.2.0 [23-Sep-2022]
---------------------
- Add DrawPage.
v 0.1.0 [21-Sep-2022]
---------------------
- Tools refactorize and documented.

View File

@ -7,7 +7,6 @@ from .easydocs import LODocuments
def __getattr__(name):
print(name)
classes = {
'active': LODocuments().active,
'active_sheet': LODocuments().active.active,

View File

@ -14,6 +14,7 @@ from .easymain import (log, DATE_OFFSET,
from .easydoc import LODocument
from .easyevents import EventsRangeSelectionListener, LOEvents
from .easyshape import LOShapes, LOShape
from .easydrawpage import LODrawPage
SECONDS_DAY = 60 * 60 * 24
@ -83,6 +84,74 @@ class LOCellStyles():
return LOCellStyle(obj)
# ~ IsFiltered,
# ~ IsManualPageBreak,
# ~ IsStartOfNewPage
class LOSheetRows():
def __init__(self, sheet, obj):
self._sheet = sheet
self._obj = obj
def __getitem__(self, index):
if isinstance(index, int):
rows = LOSheetRows(self._sheet, self.obj[index])
else:
rango = self._sheet[index.start:index.stop,0:]
rows = LOSheetRows(self._sheet, rango.obj.Rows)
return rows
def __len__(self):
return self.obj.Count
def __str__(self):
return self.obj.Name
@property
def obj(self):
return self._obj
@property
def visible(self):
return self._obj.IsVisible
@visible.setter
def visible(self, value):
self._obj.IsVisible = value
@property
def color(self):
return self.obj.CellBackColor
@color.setter
def color(self, value):
self.obj.CellBackColor = value
@property
def is_transparent(self):
return self.obj.IsCellBackgroundTransparent
@is_transparent.setter
def is_transparent(self, value):
self.obj.IsCellBackgroundTransparent = value
@property
def height(self):
return self.obj.Height
@height.setter
def height(self, value):
self.obj.Height = value
def optimal(self):
self.obj.OptimalHeight = True
return
def insert(self, index, count):
self.obj.insertByIndex(index, count)
return
def remove(self, index, count):
self.obj.removeByIndex(index, count)
return
class LOCalcRanges(object):
def __init__(self, obj):
@ -231,6 +300,10 @@ class LOCalcRange():
"""True if range is cell"""
return self._is_cell
@property
def is_range(self):
return not self._is_cell
@property
def name(self):
"""Return the range address like string"""
@ -456,6 +529,47 @@ class LOCalcRange():
cursor = self.obj.Spreadsheet.createCursorByRange(self.obj)
return cursor
# ~ To doc
@property
def position(self):
return self.obj.Position
# ~ To doc
@property
def size(self):
return self.obj.Size
@property
def height(self):
return self.obj.Size.Height
@property
def width(self):
return self.obj.Size.Width
@property
def x(self):
return self.obj.Position.X
@property
def y(self):
return self.obj.Position.Y
# ~ To doc
@property
def possize(self):
data = {
'Width': self.size.Width,
'Height': self.size.Height,
'X': self.position.X,
'Y': self.position.Y,
}
return data
@property
def rows(self):
return LOSheetRows(self.sheet, self.obj.Rows)
def clear(self, what: int=ONLY_VALUES):
"""Clear contents"""
# ~ http://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html
@ -541,10 +655,28 @@ class LOCalcSheet(BaseObject):
def password(self, value):
self.obj.protect(value)
@property
def draw_page(self):
return LODrawPage(self.obj.DrawPage)
@property
def dp(self):
return self.draw_page
@property
def shapes(self):
return self.draw_page
@property
def events(self):
return LOEvents(self.obj.Events)
@property
def height(self):
return self.obj.Size.Height
@property
def width(self):
return self.obj.Size.Width
def protect(self, value):
self.obj.protect(value)
return
@ -587,6 +719,7 @@ class LOCalcSheet(BaseObject):
return sheet
def activate(self):
"""Activate sheet"""
self.doc.activate(self.obj)
return
@ -601,6 +734,41 @@ class LOCalcSheet(BaseObject):
return cursor
class LOCalcSheetsCodeName(BaseObject):
"""Access by code name sheet"""
def __init__(self, obj):
super().__init__(obj)
self._sheets = obj.Sheets
def __getitem__(self, index):
"""Index access"""
for sheet in self._sheets:
if sheet.CodeName == index:
return LOCalcSheet(sheet)
raise IndexError
def __iter__(self):
self._i = 0
return self
def __next__(self):
"""Interation sheets"""
try:
sheet = LOCalcSheet(self._sheets[self._i])
except Exception as e:
raise StopIteration
self._i += 1
return sheet
def __contains__(self, item):
"""Contains"""
for sheet in self._sheets:
if sheet.CodeName == item:
return True
return False
class LOCalc(LODocument):
"""Classe for Calc module"""
TYPE_RANGES = ('ScCellObj', 'ScCellRangeObj')
@ -622,9 +790,11 @@ class LOCalc(LODocument):
self._sheets[key] = value
def __len__(self):
"""Count sheets"""
return self._sheets.Count
def __contains__(self, item):
"""Contains"""
return item in self._sheets
def __iter__(self):
@ -632,6 +802,7 @@ class LOCalc(LODocument):
return self
def __next__(self):
"""Interation sheets"""
try:
sheet = LOCalcSheet(self._sheets[self._i])
except Exception as e:
@ -642,6 +813,11 @@ class LOCalc(LODocument):
def __str__(self):
return f'Calc: {self.title}'
@property
def sheets(self):
"""Acces by code name sheet"""
return LOCalcSheetsCodeName(self.obj)
@property
def headers(self):
"""Get true if is visible columns/rows headers"""

View File

@ -7,8 +7,7 @@ from com.sun.star.view.SelectionType import SINGLE, MULTI, RANGE
from .easyevents import *
from .easydocs import LODocuments
from .easymain import log, TITLE, Color, BaseObject, create_instance, set_properties
from .easytools import LOInspect, Paths, Services
from .easytools import _
from .easytools import _, LOInspect, Paths, Services
__all__ = [

View File

@ -0,0 +1,233 @@
#!/usr/bin/env python3
from com.sun.star.awt import Size, Point
from .easymain import BaseObject, set_properties
from .easyshape import LOShape
DEFAULT_WH = 3000
DEFAULT_XY = 1000
# ~ class LOShapeBK(BaseObject):
# ~ @property
# ~ def cell(self):
# ~ return self.anchor
# ~ @property
# ~ def anchor(self):
# ~ obj = self.obj.Anchor
# ~ if obj.ImplementationName == OBJ_CELL:
# ~ obj = LOCalcRange(obj)
# ~ elif obj.ImplementationName == OBJ_TEXT:
# ~ obj = LOWriterTextRange(obj, LODocs().active)
# ~ else:
# ~ debug('Anchor', obj.ImplementationName)
# ~ return obj
# ~ @anchor.setter
# ~ def anchor(self, value):
# ~ if hasattr(value, 'obj'):
# ~ value = value.obj
# ~ try:
# ~ self.obj.Anchor = value
# ~ except Exception as e:
# ~ self.obj.AnchorType = value
# ~ @property
# ~ def visible(self):
# ~ return self.obj.Visible
# ~ @visible.setter
# ~ def visible(self, value):
# ~ self.obj.Visible = value
# ~ @property
# ~ def path(self):
# ~ return self.url
# ~ @property
# ~ def url(self):
# ~ url = ''
# ~ if self.is_image:
# ~ url = _P.to_system(self.obj.GraphicURL.OriginURL)
# ~ return url
# ~ @property
# ~ def mimetype(self):
# ~ mt = ''
# ~ if self.is_image:
# ~ mt = self.obj.GraphicURL.MimeType
# ~ return mt
# ~ @property
# ~ def linked(self):
# ~ l = False
# ~ if self.is_image:
# ~ l = self.obj.GraphicURL.Linked
# ~ return l
# ~ def delete(self):
# ~ self.remove()
# ~ return
# ~ def remove(self):
# ~ self.obj.Parent.remove(self.obj)
# ~ return
# ~ def save(self, path: str, mimetype=DEFAULT_MIME_TYPE):
# ~ if _P.is_dir(path):
# ~ name = self.name
# ~ ext = mimetype.lower()
# ~ else:
# ~ p = _P(path)
# ~ path = p.path
# ~ name = p.name
# ~ ext = p.ext.lower()
# ~ path = _P.join(path, f'{name}.{ext}')
# ~ args = dict(
# ~ URL = _P.to_url(path),
# ~ MimeType = MIME_TYPE[ext],
# ~ )
# ~ if not _export_image(self.obj, args):
# ~ path = ''
# ~ return path
# ~ def save2(self, path: str):
# ~ size = len(self.obj.Bitmap.DIB)
# ~ data = self.obj.GraphicStream.readBytes((), size)
# ~ data = data[-1].value
# ~ path = _P.join(path, f'{self.name}.png')
# ~ _P.save_bin(path, b'')
# ~ return
class LODrawPage(BaseObject):
_type = 'draw_page'
def __init__(self, obj):
super().__init__(obj)
def __getitem__(self, index):
if isinstance(index, int):
shape = LOShape(self.obj[index])
else:
for i, o in enumerate(self.obj):
shape = self.obj[i]
name = shape.Name or f'shape{i}'
if name == index:
shape = LOShape(shape)
break
return shape
def __iter__(self):
self._index = 0
return self
def __next__(self):
if self._index == self.count:
raise StopIteration
shape = self[self._index]
self._index += 1
return shape
def __contains__(self, source_name):
result = False
for i, o in enumerate(self.obj):
shape = self.obj[i]
name = shape.Name or f'shape{i}'
if name == source_name:
result = True
break
return result
@property
def name(self):
return self.obj.Name
@property
def doc(self):
return self.obj.Forms.Parent
@property
def width(self):
return self.obj.Width
@property
def height(self):
return self.obj.Height
@property
def count(self):
return self.obj.Count
@property
def last(self):
return self[self.count - 1]
def _create_instance(self, name):
return self.doc.createInstance(name)
def add(self, type_shape, options={}):
properties = options.copy()
"""Insert a shape in page, type shapes:
Line
Rectangle
Ellipse
Text
Connector
"""
index = self.count
default_height = DEFAULT_WH
if type_shape == 'Line':
default_height = 0
w = properties.pop('Width', DEFAULT_WH)
h = properties.pop('Height', default_height)
x = properties.pop('X', DEFAULT_XY)
y = properties.pop('Y', DEFAULT_XY)
name = properties.pop('Name', f'{type_shape.lower()}{index}')
service = f'com.sun.star.drawing.{type_shape}Shape'
shape = self._create_instance(service)
shape.Size = Size(w, h)
shape.Position = Point(x, y)
shape.Name = name
self.obj.add(shape)
if properties:
set_properties(shape, properties)
# ~ return LOShape(self.obj[index], index)
return LOShape(self.obj[index])
def remove(self, shape):
if hasattr(shape, 'obj'):
shape = shape.obj
return self.obj.remove(shape)
def remove_all(self):
while self.count:
self.obj.remove(self.obj[0])
return
def insert_image(self, path, options={}):
args = options.copy()
index = self.count
w = args.get('Width', 3000)
h = args.get('Height', 3000)
x = args.get('X', 1000)
y = args.get('Y', 1000)
name = args.get('Name', f'image{index}')
image = self.create_instance('com.sun.star.drawing.GraphicObjectShape')
if isinstance(path, str):
image.GraphicURL = _P.to_url(path)
else:
gp = create_instance('com.sun.star.graphic.GraphicProvider')
properties = dict_to_property({'InputStream': path})
image.Graphic = gp.queryGraphic(properties)
self.obj.add(image)
image.Size = Size(w, h)
image.Position = Point(x, y)
image.Name = name
return LOShape(self.obj[index], index)

View File

@ -15,8 +15,11 @@ from typing import Any, Union
import uno
import unohelper
from com.sun.star.beans import PropertyValue, NamedValue
from com.sun.star.beans import PropertyValue, NamedValue, StringPair
from com.sun.star.datatransfer import XTransferable, DataFlavor
from com.sun.star.ui.dialogs import TemplateDescription
from .messages import MESSAGES
__all__ = [
@ -144,6 +147,16 @@ _info_debug = f"Python: {sys.version}\n\n{platform.platform()}\n\n" + '\n'.join(
INFO_DEBUG = f"{NAME} v{VERSION} {LANGUAGE}\n\n{_info_debug}"
def _(msg):
if LANG == 'en':
return msg
if not LANG in MESSAGES:
return msg
return MESSAGES[LANG][msg]
def dict_to_property(values: dict, uno_any: bool=False):
"""Convert dictionary to array of PropertyValue
@ -842,6 +855,8 @@ class Paths(object):
`See API <https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1ui_1_1dialogs_1_1TemplateDescription.html>`_
"""
paths = ''
if not init_dir:
init_dir = cls.documents
init_dir = cls.to_url(init_dir)
@ -858,6 +873,7 @@ class Paths(object):
paths = [cls.to_system(p) for p in file_picker.getSelectedFiles()]
if not multiple:
paths = paths[0]
return paths
@classmethod

View File

@ -1,5 +1,8 @@
#!/usr/bin/env python3
from com.sun.star.awt import Size, Point
from .easymain import BaseObject, set_properties
class LOShapes(object):
_type = 'ShapeCollection'
@ -38,7 +41,7 @@ class LOShapes(object):
return self._obj
class LOShape():
class LOShape(BaseObject):
IMAGE = 'com.sun.star.drawing.GraphicObjectShape'
def __init__(self, obj):
@ -117,9 +120,30 @@ class LOShape():
@property
def x(self):
return self.position.X
@x.setter
def x(self, value):
self.obj.Position = Point(value, self.y)
@property
def y(self):
return self.position.Y
@y.setter
def y(self, value):
self.obj.Position = Point(self.x, value)
@property
def possize(self):
data = {
'Width': self.size.Width,
'Height': self.size.Height,
'X': self.position.X,
'Y': self.position.Y,
}
return data
@possize.setter
def possize(self, value):
self.obj.Size = Size(value['Width'], value['Height'])
self.obj.Position = Point(value['X'], value['Y'])
@property
def string(self):
@ -142,3 +166,26 @@ class LOShape():
def description(self, value):
self.obj.Description = value
@property
def in_background(self):
return self.obj.LayerID
@in_background.setter
def in_background(self, value):
self.obj.LayerID = value
@property
def layerid(self):
return self.obj.LayerID
@layerid.setter
def layerid(self, value):
self.obj.LayerID = value
@property
def is_range(self):
return False
@property
def is_cell(self):
return False

View File

@ -40,9 +40,9 @@ from com.sun.star.ui.dialogs import TemplateDescription
from .easyuno import MessageBoxType
from .easydocs import LODocuments
from .messages import MESSAGES
from .easyplus import mureq
from .easymain import (
_,
CTX,
DATE_OFFSET,
IS_MAC,
@ -96,16 +96,6 @@ FILES = {
_EVENTS = {}
def _(msg):
if LANG == 'en':
return msg
if not LANG in MESSAGES:
return msg
return MESSAGES[LANG][msg]
def debug(*messages) -> None:
"""Show messages debug