Doc for app

This commit is contained in:
El Mau 2022-03-03 23:32:55 -06:00
parent 0f2638ebaa
commit 6bfa41b43c
6 changed files with 1140 additions and 25 deletions

104
docs/source/application.rst Normal file
View File

@ -0,0 +1,104 @@
Application
===========
Remember, always import library.
.. code-block:: python
import easymacro as app
Create instances
----------------
* Instances without context
.. code-block:: python
toolkit = app.create_instance('com.sun.star.awt.Toolkit')
* Instances with context
.. code-block:: python
service = 'com.sun.star.awt.DialogProvider2'
dialog = app.create_instance(service, True)
* Get desktop
.. code-block:: python
desktop = app.create_instance('com.sun.star.frame.Desktop', True)
Or
.. code-block:: python
desktop = app.lo.desktop
Fonst
-----
* Get all fonts
.. code-block:: python
fonts = app.lo.fonts()
for f in fonts:
print(f'Name: {f.Name} - StyleName: {f.StyleName}')
Filters
-------
* Get all `support filters`_
.. code-block:: python
filters = app.lo.filters()
ds = []
for f in filters:
data = f"UI Name: {f['UIName']} - Name: {f['Name']} - Type: {f['Type']}"
app.debug(data)
Call dispatch
-------------
You can call any `dispatch command`_ used only if property or method no exists in original object or in `easymacro.py`
.. code-block:: python
doc = app.docs.active
command = 'Gallery'
app.lo.dispatch(doc, command)
Method automatically add `.uno:`
Disable or enabled commands
---------------------------
You can disable any command.
.. code-block:: python
cmd = 'OpenFromCalc'
result = app.command.disable(cmd)
app.debug(result)
And enabled.
.. code-block:: python
result = app.command.enabled(cmd)
app.debug(result)
`OpenFromCalc` is options for open documents in calc, disable or enabled menu entry and icon toolbar.
.. _dispatch command: https://wiki.documentfoundation.org/Development/DispatchCommands
.. _support filters: https://help.libreoffice.org/latest/en-US/text/shared/guide/convertfilters.html

486
docs/source/documents.rst Normal file
View File

@ -0,0 +1,486 @@
Documents
=========
Remember, always import library.
.. code-block:: python
import easymacro as app
Current doc
-----------
.. code-block:: python
doc = app.docs.active
app.msgbox(doc.title)
Iter docs
---------
.. code-block:: python
for doc in app.docs:
app.debug(doc.type, doc.title)
Count
-----
.. code-block:: python
count = len(app.docs)
app.debug(count)
Get by index
------------
.. code-block:: python
doc = app.docs[1]
app.debug(doc.type, doc.title)
Get by name
-----------
.. code-block:: python
name = 'MyDoc.ods'
if name in app.docs:
doc = app.docs[name]
app.debug(doc.type, doc.title)
If contain
----------
.. code-block:: python
result = 'myfile.ods' in app.docs
app.debug(result)
New
---
For default create new Calc document.
.. code-block:: python
doc = app.docs.new()
app.debug(doc.type)
For new Writer document.
.. code-block:: python
doc = app.docs.new('writer')
app.debug(doc.type)
With arguments.
.. code-block:: python
args= {'Hidden': True}
doc = app.docs.new('writer', args)
msg = f'{doc.type} - {doc.title}'
app.msgbox(msg)
doc.visible = True
Other documents.
.. code-block:: python
doc = app.docs.new('draw')
app.debug(doc.type)
doc = app.docs.new('impress')
app.debug(doc.type)
doc = app.docs.new('math')
app.debug(doc.type)
Open
----
.. code-block:: python
path = '/home/mau/ask_example.ods'
doc = app.docs.open(path)
While LibreOffice support format, you can open arbitrary file.
.. code-block:: python
path = '/home/mau/example.xlsx'
doc = app.docs.open(path)
With arguments.
.. code-block:: python
path = '/home/mau/example.ods'
args = {'Password': 'letmein'}
doc = app.docs.open(path, args)
Save
----
* Save new documents
.. code-block:: python
path = '/home/mau/myfile.ods'
doc = app.docs.new()
doc.save(path)
* If previously open and modify then.
.. code-block:: python
doc.save()
* Open exists file and save with other name.
.. code-block:: python
path = '/home/mau/myfile.ods'
doc = app.docs.open(path)
new_path = '/home/mau/other_name.ods'
doc.save(new_path)
Close
-----
.. code-block:: python
doc = app.docs.new()
app.msgbox(doc.title)
doc.close()
To PDF
------
* Save in path
.. code-block:: python
doc = app.active
path = '/home/mau/test.pdf'
doc.to_pdf(path)
* Save in memory
.. code-block:: python
doc = app.active
pdf = doc.to_pdf()
Export
------
* Export common formats
.. code-block:: python
doc = app.docs.new()
path = '/home/mau/myfile.xlsx'
filter_name = 'xlsx'
doc.export(path, filter_name)
path = '/home/mau/myfile.xls'
filter_name = 'xls'
doc.export(path, filter_name)
doc = app.docs.new('writer')
path = '/home/mau/myfile.docx'
filter_name = 'docx'
doc.export(path, filter_name)
path = '/home/mau/myfile.doc'
filter_name = 'doc'
doc.export(path, filter_name)
path = '/home/mau/myfile.rtf'
filter_name = 'rtf'
doc.export(path, filter_name)
* Export in memory.
.. code-block:: python
doc = app.docs.new()
filter_name = 'xlsx'
excel_doc = doc.export(filter_name=filter_name)
Properties
----------
Common properties for documents
obj
^^^
* Get original object pyUNO (read only)
.. code-block:: python
doc = app.active
app.debug(type(doc))
app.debug(type(doc.obj))
title
^^^^^
.. code-block:: python
doc = app.active
app.debug(doc.title)
doc.title = 'New title'
app.debug(doc.title)
type
^^^^
* Get type document: calc, writer, etc. (read only)
.. code-block:: python
doc = app.active
app.debug(doc.type)
uid
^^^
* Get internal RuntimeUID form document. (read only)
.. code-block:: python
doc = app.active
app.debug(doc.uid)
is_saved
^^^^^^^^
* If document is saved or not (read only)
.. code-block:: python
doc = app.active
app.debug(doc.is_saved)
is_modified
^^^^^^^^^^^
* If document has been modified (read only)
.. code-block:: python
doc = app.active
app.debug(doc.is_modified)
is_read_only
^^^^^^^^^^^^
.. code-block:: python
doc = app.active
app.debug(doc.is_read_only)
path
^^^^
* Get path of document. (read only)
.. code-block:: python
doc = app.active
app.debug(doc.path)
dir
^^^
* Get only directory from path saved (read only)
.. code-block:: python
doc = app.active
app.debug(doc.dir)
file_name
^^^^^^^^^
* Get only file name from path saved (read only)
.. code-block:: python
doc = app.active
app.debug(doc.file_name)
name
^^^^
* Get only name without extension (read only)
.. code-block:: python
doc = app.active
app.debug(doc.name)
visible
^^^^^^^
* Hide or show document.
.. code-block:: python
doc = app.active
doc.visible = False
app.msgbox(doc.visible)
doc.visible = True
zoom
^^^^
* Get or set zoom value.
.. code-block:: python
doc = app.active
zoom = doc.zoom
app.msgbox(zoom)
doc.zoom = zoom * 2
app.msgbox(doc.zoom)
doc.zoom = zoom
status_bar
^^^^^^^^^^
* Get status bar, always control in other thread.
.. code-block:: python
@app.run_in_thread
def update_status_bar(sb, text, limit):
sb.start(text, limit)
for i in range(limit):
sb.setValue(i)
app.sleep(1)
# ~ Is important free status bar
sb.end()
return
def main():
doc = app.active
update_status_bar(doc.status_bar, 'Line', 10)
return
selection
^^^^^^^^^
* **CAUTION**: Selection can be many things.
.. code-block:: python
doc = app.active
selection = doc.selection
app.debug(selection)
Methods
-------
set_focus
^^^^^^^^^
.. code-block:: python
for doc in app.docs:
app.debug(doc.title)
doc.set_focus()
app.sleep(1)
copy
^^^^
* Copy current selection
.. code-block:: python
doc = app.active
doc.copy()
paste
^^^^^
* Paste any content in clipboard
.. code-block:: python
doc = app.active
doc.paste()
paste_special
^^^^^^^^^^^^^
* Show dialog box Paste Special
.. code-block:: python
doc = app.active
doc.paste_special()
paste_values
^^^^^^^^^^^^
* Paste only values
.. code-block:: python
doc = app.active
doc.paste_values()
clear_undo
^^^^^^^^^^
* Clear history undo
.. code-block:: python
doc = app.active
doc.clear_undo()

View File

@ -1,5 +1,5 @@
easymacro module
================
API easymacro
=============
.. automodule:: easymacro
:members:

View File

@ -45,7 +45,20 @@
Dates
Email
Hash
IOStream
Json
LODocBase
LODocCalc
LODocDraw
LODocDrawImpress
LODocIDE
LODocImpress
LODocMain
LODocMath
LODocWriter
LODocument
LODocuments
LOMain
LOServer
MBT
Macro
@ -54,7 +67,7 @@
Shell
Timer
Url
commands
classproperty

View File

@ -26,7 +26,9 @@ You can used **easymacro** with any extension or directly in your macros.
tools
paths
email
api
application
documents
easymacro
Indices and tables

View File

@ -22,6 +22,7 @@ import csv
import datetime
import getpass
import hashlib
import io
import json
import logging
import os
@ -59,9 +60,11 @@ from email.utils import formatdate
from email import encoders
import uno
import unohelper
from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS
from com.sun.star.awt.MessageBoxResults import YES
from com.sun.star.beans import PropertyValue, NamedValue
from com.sun.star.io import IOException, XOutputStream
from com.sun.star.ui.dialogs import TemplateDescription
@ -303,7 +306,7 @@ def mri(obj: Any) -> None:
`See MRI <https://github.com/hanya/MRI/releases>`_
"""
mri = create_instance('mytools.Mri')
m = create_instance('mytools.Mri')
if m is None:
msg = 'Extension MRI not found'
error(msg)
@ -311,7 +314,7 @@ def mri(obj: Any) -> None:
if hasattr(obj, 'obj'):
obj = obj.obj
mri.inspect(obj)
m.inspect(obj)
return
@ -467,8 +470,9 @@ def render(template, data):
# Classes
# ~ https://github.com/django/django/blob/main/django/utils/functional.py#L61
class classproperty:
class _classproperty:
def __init__(self, method=None):
self.fget = method
@ -485,7 +489,7 @@ class Dates(object):
"""
_start = None
@_classproperty
@classproperty
def now(cls):
"""Current local date and time
@ -494,7 +498,7 @@ class Dates(object):
"""
return datetime.datetime.now().replace(microsecond=0)
@_classproperty
@classproperty
def today(cls):
"""Current local date
@ -503,7 +507,7 @@ class Dates(object):
"""
return datetime.date.today()
@_classproperty
@classproperty
def time(cls):
"""Current local time
@ -513,7 +517,7 @@ class Dates(object):
t = cls.now.time().replace(microsecond=0)
return t
@_classproperty
@classproperty
def epoch(cls):
"""Get unix time
@ -927,30 +931,30 @@ class Paths(object):
}
return data
@_classproperty
@classproperty
def home(self):
"""Get user home"""
return str(Path.home())
@_classproperty
@classproperty
def documents(self):
"""Get user save documents"""
return self.config()
@_classproperty
@classproperty
def user_profile(self):
"""Get path user profile"""
path = self.config('UserConfig')
path = str(Path(path).parent)
return path
@_classproperty
@classproperty
def user_config(self):
"""Get path config in user profile"""
path = self.config('UserConfig')
return path
@_classproperty
@classproperty
def python(self):
"""Get path executable python"""
if IS_WIN:
@ -1918,9 +1922,48 @@ class Color(object):
COLOR_ON_FOCUS = Color()('LightYellow')
class LO(object):
"""Class for LibreOffice
"""
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()
class LOMain():
"""Classe for LibreOffice"""
class _commands():
"""Class for disable and enable commands
@ -1971,7 +2014,7 @@ class LO(object):
"""
return cls._set_app_command(command, True)
@classmethod
@classmethod
def enabled(cls, command):
"""Enabled UNO command
@ -1982,12 +2025,13 @@ class LO(object):
"""
return cls._set_app_command(command, False)
@_classproperty
# ~ @classproperty
def cmd(cls):
"""Disable or enable commands"""
return cls._commands
@_classproperty
def desktop(cls) -> Any:
# ~ @classproperty
def desktop(cls):
"""Create desktop instance
:return: Desktop instance
@ -2046,6 +2090,469 @@ class LO(object):
return rows
class LODocument():
def __init__(self, obj):
self._obj = obj
self._cc = obj.getCurrentController()
self._undo = True
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
@property
def obj(self):
"""Return original pyUno object"""
return self._obj
@property
def type(self):
"""Get type document"""
return self._type
@property
def frame(self):
"""Get frame document"""
return self._cc.getFrame()
@property
def title(self):
"""Get title document"""
return self.obj.getTitle()
@title.setter
def title(self, value):
self.obj.setTitle(value)
@property
def uid(self):
"""Get Runtime UID"""
return self.obj.RuntimeUID
@property
def is_saved(self):
"""Get is saved"""
return self.obj.hasLocation()
@property
def is_modified(self):
"""Get is modified"""
return self.obj.isModified()
@property
def is_read_only(self):
"""Get is read only"""
return self.obj.isReadonly()
@property
def path(self):
"""Get path in system files"""
return Paths.to_system(self.obj.URL)
@property
def dir(self):
"""Get directory from path"""
return Paths(self.path).path
@property
def file_name(self):
"""Get only file name"""
return Paths(self.path).file_name
@property
def name(self):
"""Get name without extension"""
return Paths(self.path).name
@property
def visible(self):
"""Get windows visible"""
w = self.frame.ContainerWindow
return w.isVisible()
@visible.setter
def visible(self, value):
w = self.frame.ContainerWindow
w.setVisible(value)
@property
def zoom(self):
"""Get current zoom value"""
return self._cc.ZoomValue
@zoom.setter
def zoom(self, value):
self._cc.ZoomValue = value
@property
def status_bar(self):
"""Get status bar"""
bar = self._cc.getStatusIndicator()
return bar
@property
def selection(self):
"""Get current selecction"""
sel = self.obj.CurrentSelection
return sel
@property
def table_auto_formats(self):
taf = create_instance('com.sun.star.sheet.TableAutoFormats')
return taf.ElementNames
def save(self, path: str='', args: dict={}) -> bool:
"""Save document
:param path: Path to save document
:type path: str
:param args: Optional: Extra argument for save
:type args: dict
:return: True if save correctly, False if not
:rtype: bool
"""
if not path:
self.obj.store()
return True
path_save = Paths.to_url(path)
opt = dict_to_property(args)
try:
self.obj.storeAsURL(path_save, opt)
except Exception as e:
error(e)
return False
return True
def close(self):
"""Close document"""
self.obj.close(True)
return
def to_pdf(self, path: str='', args: dict={}):
"""Export to PDF
:param path: Path to export document
:type path: str
:param args: Optional: Extra argument for export
:type args: dict
:return: None if path or stream in memory
:rtype: bytes or None
`See PDF Export <https://wiki.documentfoundation.org/Macros/Python_Guide/PDF_export_filter_data>`_
"""
stream = None
path_pdf = 'private:stream'
filter_name = f'{self.type}_pdf_Export'
filter_data = dict_to_property(args, True)
filters = {
'FilterName': filter_name,
'FilterData': filter_data,
}
if path:
path_pdf = Paths.to_url(path)
else:
stream = IOStream.output()
filters['OutputStream'] = stream
opt = dict_to_property(filters)
try:
self.obj.storeToURL(path_pdf, opt)
except Exception as e:
error(e)
if not stream is None:
stream = stream.buffer
return stream
def export(self, path: str='', filter_name: str='', args: dict={}):
"""Export to others formats
:param path: Path to export document
:type path: str
:param filter_name: Filter name to export
:type filter_name: str
:param args: Optional: Extra argument for export
:type args: dict
:return: None if path or stream in memory
:rtype: bytes or None
"""
FILTERS = {
'xlsx': 'Calc MS Excel 2007 XML',
'xls': 'MS Excel 97',
'docx': 'MS Word 2007 XML',
'doc': 'MS Word 97',
'rtf': 'Rich Text Format',
}
stream = None
path_target = 'private:stream'
filter_name = FILTERS.get(filter_name, filter_name)
filter_data = dict_to_property(args, True)
filters = {
'FilterName': filter_name,
'FilterData': filter_data,
}
if path:
path_target = Paths.to_url(path)
else:
stream = IOStream.output()
filters['OutputStream'] = stream
opt = dict_to_property(filters)
try:
self.obj.storeToURL(path_target, opt)
except Exception as e:
error(e)
if not stream is None:
stream = stream.buffer
return stream
def _create_instance(self, name):
obj = self.obj.createInstance(name)
return obj
def set_focus(self):
"""Send focus to windows"""
w = self.frame.ComponentWindow
w.setFocus()
return
def copy(self):
"""Copy current selection"""
LOMain.dispatch(self.frame, 'Copy')
return
def paste(self):
"""Paste current content in clipboard"""
sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard')
transferable = sc.getContents()
self._cc.insertTransferable(transferable)
return
def paste_special(self):
"""Insert contents, show dialog box Paste Special"""
LOMain.dispatch(self.frame, 'InsertContents')
return
def paste_values(self):
"""Paste only values"""
args = {
'Flags': 'SVDT',
# ~ 'FormulaCommand': 0,
# ~ 'SkipEmptyCells': False,
# ~ 'Transpose': False,
# ~ 'AsLink': False,
# ~ 'MoveMode': 4,
}
LOMain.dispatch(self.frame, 'InsertContents', args)
return
def clear_undo(self):
"""Clear history undo"""
self.obj.getUndoManager().clear()
return
class LODocMain():
_type = 'main'
def __init__(self, obj):
self._obj = obj
@property
def obj(self):
return self._obj
@property
def type(self):
return self._type
class LODocCalc(LODocument):
_type = 'calc'
def __init__(self, obj):
super().__init__(obj)
class LODocWriter(LODocument):
_type = 'writer'
def __init__(self, obj):
super().__init__(obj)
self._view_settings = self._cc.ViewSettings
@property
def zoom(self):
return self._view_settings.ZoomValue
@zoom.setter
def zoom(self, value):
self._view_settings.ZoomValue = value
class LODocDrawImpress(LODocument):
def __init__(self, obj):
super().__init__(obj)
class LODocDraw(LODocDrawImpress):
_type = 'draw'
def __init__(self, obj):
super().__init__(obj)
class LODocImpress(LODocDrawImpress):
_type = 'impress'
def __init__(self, obj):
super().__init__(obj)
class LODocMath(LODocDrawImpress):
_type = 'math'
def __init__(self, obj):
super().__init__(obj)
class LODocBase(LODocument):
_type = 'base'
def __init__(self, obj):
super().__init__(obj)
class LODocIDE(LODocument):
_type = 'basicide'
def __init__(self, obj):
super().__init__(obj)
class LODocuments():
"""Classe for documents
"""
_classes = {
'com.sun.star.sheet.SpreadsheetDocument': LODocCalc,
'com.sun.star.text.TextDocument': LODocWriter,
'com.sun.star.drawing.DrawingDocument': LODocDraw,
'com.sun.star.presentation.PresentationDocument': LODocImpress,
'com.sun.star.formula.FormulaProperties': LODocMath,
'com.sun.star.script.BasicIDE': LODocIDE,
'com.sun.star.sdb.OfficeDatabaseDocument': LODocBase,
'com.sun.star.frame.StartModule': LODocMain
}
# ~ BASE: 'com.sun.star.sdb.DocumentDataSource',
_desktop = LOMain.desktop
def __len__(self):
# ~ len(self._desktop.Components)
for i, _ in enumerate(self._desktop.Components):
pass
return i + 1
def __getitem__(self, index):
# ~ self._desktop.Components[index]
obj = None
for i, doc in enumerate(self._desktop.Components):
if isinstance(index, int) and i == index:
obj = self._get_class_doc(doc)
break
elif isinstance(index, str) and doc.Title == index:
obj = self._get_class_doc(doc)
break
return obj
def __contains__(self, item):
doc = self[item]
return not doc is None
def __iter__(self):
self._i = -1
return self
def __next__(self):
self._i += 1
doc = self[self._i]
if doc is None:
raise StopIteration
else:
return doc
def _get_class_doc(self, doc):
"""Identify type doc"""
main = 'com.sun.star.frame.StartModule'
if doc.supportsService(main):
return self._classes[main](doc)
mm = create_instance('com.sun.star.frame.ModuleManager')
type_module = mm.identify(doc)
return self._classes[type_module](doc)
@property
def active(self):
"""Get active doc"""
doc = self._desktop.getCurrentComponent()
obj = self._get_class_doc(doc)
return obj
def new(self, type_doc: str='calc', args: dict={}):
"""Create new document
:param type_doc: The type doc to create, default is Calc
:type type_doc: str
:param args: Extra argument
:type args: dict
:return: New document
:rtype: Custom classe
"""
url = f'private:factory/s{type_doc}'
opt = dict_to_property(args)
doc = self._desktop.loadComponentFromURL(url, '_default', 0, opt)
obj = self._get_class_doc(doc)
return obj
def open(self, path: str, args: dict={}):
""" Open document from path
:param path: Path to document
:type path: str
:param args: Extra argument
Usually options:
Hidden: True or False
AsTemplate: True or False
ReadOnly: True or False
Password: super_secret
MacroExecutionMode: 4 = Activate macros
Preview: True or False
:type args: dict
`See API XComponentLoader <http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1frame_1_1XComponentLoader.html>`_
`See API MediaDescriptor <http://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1document_1_1MediaDescriptor.html>`_
"""
url = Paths.to_url(path)
opt = dict_to_property(args)
doc = self._desktop.loadComponentFromURL(url, '_default', 0, opt)
if doc is None:
return
obj = self._get_class_doc(doc)
return obj
def __getattr__(name):
classes = {
'dates': Dates,
@ -2059,8 +2566,11 @@ def __getattr__(name):
'url': Url,
'email': Email,
'color': Color(),
'lo': LO,
'desktop': LO.desktop,
'io': IOStream,
'lo': LOMain,
'command': LOMain.cmd,
'docs': LODocuments(),
'active': LODocuments().active,
}
if name in classes:
return classes[name]