Update easymacro

This commit is contained in:
Mauricio Baeza 2019-11-22 19:34:48 -06:00
parent a600b12dc4
commit 7111cca36b
13 changed files with 999 additions and 144 deletions

View File

@ -1,3 +1,7 @@
v 0.5.0 [22-nov-2019]
- Update easymacro.py
v 0.4.0 [23-oct-2019] v 0.4.0 [23-oct-2019]
- Fix error in main - Fix error in main

View File

@ -9,11 +9,12 @@ https://gitlab.com/mauriciobaeza/zaz
### Software libre, no gratis ### Software libre, no gratis
This extension have a cost of maintenance of 1 euro every year. This extension have a cost of maintenance of 1 euro every year.
BCH: `1RPLWHJW34p7pMQV1ft4x7eWhAYw69Dsb` BCH: `qztd3l00xle5tffdqvh2snvadkuau2ml0uqm4n875d`
BTC: `3Fe4JuADrAK8Qs7GDAxbSXR8E54avwZJLW` BTC: `3FhiXcXmAesmQzrNEngjHFnvaJRhU1AGWV`
PayPal :( donate ATT elmau DOT net PayPal :( donate ATT elmau DOT net

View File

@ -1,2 +1,2 @@
0.4.0 0.5.0

View File

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

View File

@ -34,6 +34,7 @@ import shlex
import shutil import shutil
import socket import socket
import subprocess import subprocess
import ssl
import sys import sys
import tempfile import tempfile
import threading import threading
@ -41,13 +42,9 @@ import time
import traceback import traceback
import zipfile import zipfile
# ~ from collections import OrderedDict
# ~ from collections.abc import MutableMapping
from functools import wraps from functools import wraps
from operator import itemgetter
from pathlib import Path, PurePath from pathlib import Path, PurePath
from pprint import pprint from pprint import pprint
from enum import IntEnum
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError from urllib.error import URLError, HTTPError
from string import Template from string import Template
@ -91,14 +88,10 @@ from com.sun.star.awt import XMenuListener
from com.sun.star.awt import XKeyListener from com.sun.star.awt import XKeyListener
from com.sun.star.awt import XItemListener from com.sun.star.awt import XItemListener
from com.sun.star.awt import XFocusListener from com.sun.star.awt import XFocusListener
from com.sun.star.awt import XTabListener
from com.sun.star.awt.grid import XGridDataListener
from com.sun.star.awt.grid import XGridSelectionListener
class FontSlant(IntEnum):
NONE = 0
OBLIQUE = 1
ITALIC = 2
DONTKNOW = 3
REVERSE_OBLIQUE = 4
REVERSE_ITALIC = 5
try: try:
from fernet import Fernet, InvalidToken from fernet import Fernet, InvalidToken
@ -119,7 +112,6 @@ KEY = {
SEPARATION = 5 SEPARATION = 5
MSG_LANG = { MSG_LANG = {
'es': { 'es': {
'OK': 'Aceptar', 'OK': 'Aceptar',
@ -130,35 +122,36 @@ MSG_LANG = {
} }
} }
OS = platform.system() OS = platform.system()
USER = getpass.getuser() USER = getpass.getuser()
PC = platform.node() PC = platform.node()
DESKTOP = os.environ.get('DESKTOP_SESSION', '') DESKTOP = os.environ.get('DESKTOP_SESSION', '')
INFO_DEBUG = '{}\n\n{}\n\n{}'.format(sys.version, platform.platform(), '\n'.join(sys.path)) INFO_DEBUG = '{}\n\n{}\n\n{}'.format(sys.version, platform.platform(), '\n'.join(sys.path))
IS_WIN = OS == 'Windows' IS_WIN = OS == 'Windows'
LOG_NAME = 'ZAZ' LOG_NAME = 'ZAZ'
CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16' CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16'
PYTHON = 'python' PYTHON = 'python'
if IS_WIN: if IS_WIN:
PYTHON = 'python.exe' PYTHON = 'python.exe'
CALC = 'calc' CALC = 'calc'
WRITER = 'writer' WRITER = 'writer'
OBJ_CELL = 'ScCellObj' OBJ_CELL = 'ScCellObj'
OBJ_RANGE = 'ScCellRangeObj' OBJ_RANGE = 'ScCellRangeObj'
OBJ_RANGES = 'ScCellRangesObj' OBJ_RANGES = 'ScCellRangesObj'
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES) OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
TEXT_RANGE = 'SwXTextRange'
TEXT_RANGES = 'SwXTextRanges'
TEXT_TYPE_RANGES = (TEXT_RANGE, TEXT_RANGES)
TYPE_DOC = { TYPE_DOC = {
'calc': 'com.sun.star.sheet.SpreadsheetDocument', 'calc': 'com.sun.star.sheet.SpreadsheetDocument',
'writer': 'com.sun.star.text.TextDocument', 'writer': 'com.sun.star.text.TextDocument',
'impress': 'com.sun.star.presentation.PresentationDocument', 'impress': 'com.sun.star.presentation.PresentationDocument',
'draw': 'com.sun.star.drawing.DrawingDocument', 'draw': 'com.sun.star.drawing.DrawingDocument',
# ~ 'base': 'com.sun.star.sdb.OfficeDatabaseDocument',
'base': 'com.sun.star.sdb.DocumentDataSource', 'base': 'com.sun.star.sdb.DocumentDataSource',
'math': 'com.sun.star.formula.FormulaProperties', 'math': 'com.sun.star.formula.FormulaProperties',
'basic': 'com.sun.star.script.BasicIDE', 'basic': 'com.sun.star.script.BasicIDE',
@ -197,19 +190,16 @@ MENUS_WRITER = {
'windows': '.uno:WindowList', 'windows': '.uno:WindowList',
'help': '.uno:HelpMenu', 'help': '.uno:HelpMenu',
} }
MENUS_APP = { MENUS_APP = {
'main': MENUS_MAIN, 'main': MENUS_MAIN,
'calc': MENUS_CALC, 'calc': MENUS_CALC,
'writer': MENUS_WRITER, 'writer': MENUS_WRITER,
} }
EXT = { EXT = {
'pdf': 'pdf', 'pdf': 'pdf',
} }
FILE_NAME_DEBUG = 'debug.odt' FILE_NAME_DEBUG = 'debug.odt'
FILE_NAME_CONFIG = 'zaz-{}.json' FILE_NAME_CONFIG = 'zaz-{}.json'
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
@ -279,6 +269,12 @@ def mri(obj):
return return
def inspect(obj):
zaz = create_instance('net.elmau.zaz.inspect')
zaz.inspect(obj)
return
def catch_exception(f): def catch_exception(f):
@wraps(f) @wraps(f)
def func(*args, **kwargs): def func(*args, **kwargs):
@ -454,12 +450,14 @@ def call_dispatch(url, args=()):
return return
def get_temp_file(): def get_temp_file(only_name=False):
delete = True delete = True
if IS_WIN: if IS_WIN:
delete = False delete = False
return tempfile.NamedTemporaryFile(delete=delete) tmp = tempfile.NamedTemporaryFile(delete=delete)
if only_name:
tmp = tmp.name
return tmp
def _path_url(path): def _path_url(path):
if path.startswith('file://'): if path.startswith('file://'):
@ -501,6 +499,11 @@ def dict_to_property(values, uno_any=False):
return ps return ps
def dict_to_named(values):
ps = tuple([NamedValue(n, v) for n, v in values.items()])
return ps
def property_to_dict(values): def property_to_dict(values):
d = {i.Name: i.Value for i in values} d = {i.Name: i.Value for i in values}
return d return d
@ -934,6 +937,67 @@ class LOCellStyles(object):
return 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): class LOCalc(LODocument):
def __init__(self, obj): def __init__(self, obj):
@ -942,7 +1006,9 @@ class LOCalc(LODocument):
def __getitem__(self, index): def __getitem__(self, index):
if isinstance(index, str): if isinstance(index, str):
index = [s.Name for s in self._sheets if s.CodeName == index][0] or index code_name = [s.Name for s in self._sheets if s.CodeName == index]
if code_name:
index = code_name[0]
return LOCalcSheet(self._sheets[index], self) return LOCalcSheet(self._sheets[index], self)
def __setitem__(self, key, value): def __setitem__(self, key, value):
@ -1182,7 +1248,7 @@ class LOCalcSheet(object):
def _init_values(self): def _init_values(self):
self._events = None self._events = None
self._dp = self.obj.getDrawPage() self._dp = self.obj.getDrawPage()
return self._images = {i.Name: LOImage(i) for i in self._dp}
@property @property
def obj(self): def obj(self):
@ -1192,6 +1258,10 @@ class LOCalcSheet(object):
def doc(self): def doc(self):
return self._doc return self._doc
@property
def images(self):
return self._images
@property @property
def name(self): def name(self):
return self._obj.Name return self._obj.Name
@ -1306,7 +1376,11 @@ class LOWriter(LODocument):
@property @property
def selection(self): def selection(self):
sel = self.obj.getCurrentSelection() sel = self.obj.getCurrentSelection()
return LOTextRange(sel[0]) if sel.ImplementationName == TEXT_RANGES:
return LOTextRange(sel[0])
elif sel.ImplementationName == TEXT_RANGE:
return LOTextRange(sel)
return sel
def write(self, data, cursor=None): def write(self, data, cursor=None):
cursor = cursor or self.selection.cursor.getEnd() cursor = cursor or self.selection.cursor.getEnd()
@ -1583,7 +1657,7 @@ class LODrawImpress(LODocument):
def insert_image(self, path, **kwargs): def insert_image(self, path, **kwargs):
w = kwargs.get('width', 3000) w = kwargs.get('width', 3000)
h = kwargs.get('Height', 1000) h = kwargs.get('Height', 3000)
x = kwargs.get('X', 1000) x = kwargs.get('X', 1000)
y = kwargs.get('Y', 1000) y = kwargs.get('Y', 1000)
@ -1640,6 +1714,9 @@ class LOCellRange(object):
def __getitem__(self, index): def __getitem__(self, index):
return LOCellRange(self.obj[index], self.doc) return LOCellRange(self.obj[index], self.doc)
def __contains__(self, item):
return item.in_range(self)
def _init_values(self): def _init_values(self):
self._type_obj = self.obj.ImplementationName self._type_obj = self.obj.ImplementationName
self._type_content = EMPTY self._type_content = EMPTY
@ -1689,7 +1766,7 @@ class LOCellRange(object):
self.obj.setFormula(data) self.obj.setFormula(data)
else: else:
self.obj.setString(data) self.obj.setString(data)
elif isinstance(data, (int, float)): elif isinstance(data, (int, float, bool)):
self.obj.setValue(data) self.obj.setValue(data)
elif isinstance(data, datetime.datetime): elif isinstance(data, datetime.datetime):
d = data.toordinal() d = data.toordinal()
@ -1707,8 +1784,6 @@ class LOCellRange(object):
return self.obj.getDataArray() return self.obj.getDataArray()
@data.setter @data.setter
def data(self, values): def data(self, values):
if isinstance(values, list):
values = tuple(values)
self.obj.setDataArray(values) self.obj.setDataArray(values)
@property @property
@ -1716,8 +1791,6 @@ class LOCellRange(object):
return self.obj.getFormulaArray() return self.obj.getFormulaArray()
@formula.setter @formula.setter
def formula(self, values): def formula(self, values):
if isinstance(values, list):
values = tuple(values)
self.obj.setFormulaArray(values) self.obj.setFormulaArray(values)
@property @property
@ -1742,13 +1815,19 @@ class LOCellRange(object):
cursor.collapseToSize(cols, rows) cursor.collapseToSize(cols, rows)
return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc) return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc)
def copy_from(self, rango): def copy_from(self, rango, formula=False):
data = rango data = rango
if isinstance(rango, LOCellRange): if isinstance(rango, LOCellRange):
data = rango.data if formula:
data = rango.formula
else:
data = rango.data
rows = len(data) rows = len(data)
cols = len(data[0]) cols = len(data[0])
self.to_size(rows, cols).data = data if formula:
self.to_size(rows, cols).formula = data
else:
self.to_size(rows, cols).data = data
return return
def copy_to(self, cell, formula=False): def copy_to(self, cell, formula=False):
@ -1759,6 +1838,10 @@ class LOCellRange(object):
rango.data = self.data rango.data = self.data
return return
def copy(self, source):
self.sheet.obj.copyRange(self.address, source.range_address)
return
def offset(self, row=1, col=0): def offset(self, row=1, col=0):
ra = self.obj.getRangeAddress() ra = self.obj.getRangeAddress()
col = ra.EndColumn + col col = ra.EndColumn + col
@ -1816,6 +1899,10 @@ class LOCellRange(object):
a = self.obj.getRangeAddressesAsString() a = self.obj.getRangeAddressesAsString()
return a return a
@property
def range_address(self):
return self.obj.getRangeAddress()
@property @property
def current_region(self): def current_region(self):
cursor = self.sheet.get_cursor(self.obj[0,0]) cursor = self.sheet.get_cursor(self.obj[0,0])
@ -1986,6 +2073,10 @@ class EventsListenerBase(unohelper.Base, XEventListener):
self._name = name self._name = name
self._window = window self._window = window
@property
def name(self):
return self._name
def disposing(self, event): def disposing(self, event):
self._controller = None self._controller = None
if not self._window is None: if not self._window is None:
@ -2096,7 +2187,10 @@ class EventsItem(EventsListenerBase, XItemListener):
pass pass
def itemStateChanged(self, event): def itemStateChanged(self, event):
pass event_name = '{}_item_changed'.format(self.name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
class EventsItemRoadmap(EventsItem): class EventsItemRoadmap(EventsItem):
@ -2145,6 +2239,45 @@ class EventsKey(EventsListenerBase, XKeyListener):
return 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 EventsGrid(EventsListenerBase, XGridDataListener, XGridSelectionListener):
def __init__(self, controller, name):
super().__init__(controller, name)
def dataChanged(self, event):
event_name = '{}_data_changed'.format(self.name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
def rowHeadingChanged(self, event):
pass
def rowsInserted(self, event):
pass
def rowsRemoved(self, evemt):
pass
def selectionChanged(self, event):
event_name = '{}_selection_changed'.format(self.name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
class EventsKeyWindow(EventsListenerBase, XKeyListener): class EventsKeyWindow(EventsListenerBase, XKeyListener):
""" """
event.KeyChar event.KeyChar
@ -2221,8 +2354,8 @@ class EventsWindow(EventsListenerBase, XTopWindowListener, XWindowListener):
# ~ XWindowListener # ~ XWindowListener
def windowResized(self, event): def windowResized(self, event):
# ~ sb = self._container.getControl('subcontainer') sb = self._cls._subcont
# ~ sb.setPosSize(0, 0, event.Width, event.Height, SIZE) sb.setPosSize(0, 0, event.Width, event.Height, SIZE)
event_name = '{}_resized'.format(self._name) event_name = '{}_resized'.format(self._name)
if hasattr(self._controller, event_name): if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event) getattr(self._controller, event_name)(event)
@ -2284,6 +2417,7 @@ class UnoBaseObject(object):
@property @property
def parent(self): def parent(self):
ps = self.obj.getContext().PosSize
return self.obj.getContext() return self.obj.getContext()
def _get_possize(self, name): def _get_possize(self, name):
@ -2325,17 +2459,23 @@ class UnoBaseObject(object):
return self._model.Width return self._model.Width
@width.setter @width.setter
def width(self, value): def width(self, value):
self._model.Width = value if hasattr(self.model, 'Width'):
self.model.Width = value
elif hasattr(self.obj, 'PosSize'):
self._set_possize('Width', value)
@property @property
def height(self): def height(self):
if hasattr(self._model, 'Height'): if hasattr(self.model, 'Height'):
return self._model.Height return self.model.Height
ps = self.obj.getPosSize() ps = self.obj.getPosSize()
return ps.Height return ps.Height
@height.setter @height.setter
def height(self, value): def height(self, value):
self._model.Height = value if hasattr(self.model, 'Height'):
self.model.Height = value
elif hasattr(self.obj, 'PosSize'):
self._set_possize('Height', value)
@property @property
def tag(self): def tag(self):
@ -2398,8 +2538,12 @@ class UnoBaseObject(object):
def move(self, origin, x=0, y=5): def move(self, origin, x=0, y=5):
if x: if x:
self.x = origin.x + origin.width + x self.x = origin.x + origin.width + x
else:
self.x = origin.x
if y: if y:
self.y = origin.y + origin.height + y self.y = origin.y + origin.height + y
else:
self.y = origin.y
return return
def possize(self, origin): def possize(self, origin):
@ -2568,16 +2712,19 @@ class UnoGrid(UnoBaseObject):
# ~ def format_columns(self, value): # ~ def format_columns(self, value):
# ~ self._format_columns = value # ~ self._format_columns = value
@property
def value(self):
return self[self.column, self.row]
@property @property
def data(self): def data(self):
return self._data return self._data
@data.setter @data.setter
def data(self, values): def data(self, values):
# ~ self._data = values # ~ self._data = values
self._gdm.removeAllRows() self.clear()
headings = tuple(range(1, len(values) + 1)) headings = tuple(range(1, len(values) + 1))
self._gdm.addRows(headings, values) self._gdm.addRows(headings, values)
# ~ rows = range(grid_dm.RowCount) # ~ rows = range(grid_dm.RowCount)
# ~ colors = [COLORS['GRAY'] if r % 2 else COLORS['WHITE'] for r in rows] # ~ colors = [COLORS['GRAY'] if r % 2 else COLORS['WHITE'] for r in rows]
# ~ grid.Model.RowBackgroundColors = tuple(colors) # ~ grid.Model.RowBackgroundColors = tuple(colors)
@ -2617,6 +2764,10 @@ class UnoGrid(UnoBaseObject):
row.append(d) row.append(d)
return tuple(row) return tuple(row)
def clear(self):
self._gdm.removeAllRows()
return
def add_row(self, data): def add_row(self, data):
# ~ self._data.append(data) # ~ self._data.append(data)
data = self._validate_column(data) data = self._validate_column(data)
@ -2626,18 +2777,17 @@ class UnoGrid(UnoBaseObject):
def remove_row(self, row): def remove_row(self, row):
self._gdm.removeRow(row) self._gdm.removeRow(row)
# ~ del self._data[row] # ~ del self._data[row]
self._update_row_heading() self.update_row_heading()
return return
def _update_row_heading(self): def update_row_heading(self):
for i in range(self.rows): for i in range(self.rows):
self._gdm.updateRowHeading(i, i + 1) self._gdm.updateRowHeading(i, i + 1)
return return
def sort(self, column, asc=True): def sort(self, column, asc=True):
self._gdm.sortByColumn(column, asc) self._gdm.sortByColumn(column, asc)
# ~ self._data.sort(key=itemgetter(column), reverse=not asc) self.update_row_heading()
self._update_row_heading()
return return
def set_column_image(self, column, path): def set_column_image(self, column, path):
@ -2685,7 +2835,6 @@ class UnoRoadmap(UnoBaseObject):
class UnoTree(UnoBaseObject): class UnoTree(UnoBaseObject):
@catch_exception
def __init__(self, obj, ): def __init__(self, obj, ):
super().__init__(obj) super().__init__(obj)
self._tdm = None self._tdm = None
@ -2738,6 +2887,119 @@ class UnoTree(UnoBaseObject):
return return
class UnoTab(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()
@property
def active(self):
return self.current
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'] = _set_column_model(columns)
if not 'Width' in properties:
properties['Width'] = self.width
if not 'Height' in properties:
properties['Height'] = self.height
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): def get_custom_class(tipo, obj):
classes = { classes = {
'label': UnoLabel, 'label': UnoLabel,
@ -2748,7 +3010,7 @@ def get_custom_class(tipo, obj):
'link': UnoLabelLink, 'link': UnoLabelLink,
'roadmap': UnoRoadmap, 'roadmap': UnoRoadmap,
'tree': UnoTree, 'tree': UnoTree,
# ~ 'tab': UnoTab, 'tab': UnoTab,
# ~ 'image': UnoImage, # ~ 'image': UnoImage,
# ~ 'radio': UnoRadio, # ~ 'radio': UnoRadio,
# ~ 'groupbox': UnoGroupBox, # ~ 'groupbox': UnoGroupBox,
@ -2757,6 +3019,24 @@ def get_custom_class(tipo, obj):
return classes[tipo](obj) 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',
'tab': 'com.sun.star.awt.UnoMultiPageModel',
}
return services[control]
def add_listeners(events, control, name=''): def add_listeners(events, control, name=''):
listeners = { listeners = {
'addActionListener': EventsButton, 'addActionListener': EventsButton,
@ -2764,6 +3044,7 @@ def add_listeners(events, control, name=''):
'addItemListener': EventsItem, 'addItemListener': EventsItem,
'addFocusListener': EventsFocus, 'addFocusListener': EventsFocus,
'addKeyListener': EventsKey, 'addKeyListener': EventsKey,
'addTabListener': EventsTab,
} }
if hasattr(control, 'obj'): if hasattr(control, 'obj'):
control = contro.obj control = contro.obj
@ -2785,6 +3066,11 @@ def add_listeners(events, control, name=''):
continue continue
getattr(control, key)(listeners[key](events, name)) getattr(control, key)(listeners[key](events, name))
if is_grid:
controllers = EventsGrid(events, name)
control.addSelectionListener(controllers)
control.Model.GridDataModel.addGridDataListener(controllers)
return return
@ -3174,6 +3460,7 @@ class LOChart(object):
chart_data.setData(data) chart_data.setData(data)
chart_data.RowDescriptions = labels chart_data.RowDescriptions = labels
# ~ Bug
if tipo == 'Pie': if tipo == 'Pie':
chart.setDiagram(chart.createInstance(self.BASE.format('Bar'))) chart.setDiagram(chart.createInstance(self.BASE.format('Bar')))
chart.setDiagram(chart.createInstance(self.BASE.format('Pie'))) chart.setDiagram(chart.createInstance(self.BASE.format('Pie')))
@ -3225,6 +3512,29 @@ class LOChart(object):
return self return self
def _set_column_model(columns):
#~ https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1grid_1_1XGridColumn.html
column_model = create_instance('com.sun.star.awt.grid.DefaultGridColumnModel', True)
for column in columns:
grid_column = create_instance('com.sun.star.awt.grid.GridColumn', True)
for k, v in column.items():
setattr(grid_column, k, v)
column_model.addColumn(grid_column)
return column_model
def _set_image_url(image, id_extension=''):
if exists_path(image):
return _path_url(image)
if not id_extension:
return ''
path = get_path_extension(id_extension)
path = join(path, DIR['images'], image)
return _path_url(path)
class LODialog(object): class LODialog(object):
def __init__(self, **properties): def __init__(self, **properties):
@ -3278,6 +3588,7 @@ class LODialog(object):
'stardiv.Toolkit.UnoButtonControl': 'button', 'stardiv.Toolkit.UnoButtonControl': 'button',
'stardiv.Toolkit.UnoListBoxControl': 'listbox', 'stardiv.Toolkit.UnoListBoxControl': 'listbox',
'stardiv.Toolkit.UnoRoadmapControl': 'roadmap', 'stardiv.Toolkit.UnoRoadmapControl': 'roadmap',
'stardiv.Toolkit.UnoMultiPageControl': 'pages',
} }
return types[name] return types[name]
@ -3375,6 +3686,7 @@ class LODialog(object):
'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel', 'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel',
'image': 'com.sun.star.awt.UnoControlImageControlModel', 'image': 'com.sun.star.awt.UnoControlImageControlModel',
'radio': 'com.sun.star.awt.UnoControlRadioButtonModel', 'radio': 'com.sun.star.awt.UnoControlRadioButtonModel',
'pages': 'com.sun.star.awt.UnoMultiPageModel',
} }
return services[control] return services[control]
@ -3410,11 +3722,18 @@ class LODialog(object):
properties['Height'] = self.height properties['Height'] = self.height
if 'Title' in properties: if 'Title' in properties:
properties['Text'] = properties.pop('Title') properties['Text'] = properties.pop('Title')
elif tipo == 'tab':
if not 'Width' in properties:
properties['Width'] = self.width
if not 'Height' in properties:
properties['Height'] = self.height
return properties return properties
def add_control(self, properties): def add_control(self, properties):
tipo = properties.pop('Type').lower() tipo = properties.pop('Type').lower()
root = properties.pop('Root', '') root = properties.pop('Root', '')
sheets = properties.pop('Sheets', ())
properties = self._special_properties(tipo, properties) properties = self._special_properties(tipo, properties)
model = self.model.createInstance(self._get_control_model(tipo)) model = self.model.createInstance(self._get_control_model(tipo))
@ -3427,6 +3746,9 @@ class LODialog(object):
if tipo == 'tree' and root: if tipo == 'tree' and root:
control.root = root control.root = root
elif tipo == 'pages' and sheets:
control.sheets = sheets
control.events = self.events
setattr(self, name, control) setattr(self, name, control)
return return
@ -3459,13 +3781,26 @@ class LODialog(object):
class LOWindow(object): class LOWindow(object):
EMPTY = b"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dlg:window PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "dialog.dtd">
<dlg:window xmlns:dlg="http://openoffice.org/2000/dialog" xmlns:script="http://openoffice.org/2000/script" dlg:id="empty" dlg:left="0" dlg:top="0" dlg:width="0" dlg:height="0" dlg:closeable="true" dlg:moveable="true" dlg:withtitlebar="false"/>"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
self._events = None self._events = None
self._menu = None self._menu = None
self._container = None self._container = None
self._id_extension = ''
self._obj = self._create(kwargs) self._obj = self._create(kwargs)
@property
def id_extension(self):
return self._id_extension
@id_extension.setter
def id_extension(self, value):
global ID_EXTENSION
ID_EXTENSION = value
self._id_extension = value
def _create(self, properties): def _create(self, properties):
ps = ( ps = (
properties.get('X', 0), properties.get('X', 0),
@ -3476,6 +3811,7 @@ class LOWindow(object):
self._title = properties.get('Title', TITLE) self._title = properties.get('Title', TITLE)
self._create_frame(ps) self._create_frame(ps)
self._create_container(ps) self._create_container(ps)
self._create_subcontainer(ps)
# ~ self._create_splitter(ps) # ~ self._create_splitter(ps)
return return
@ -3507,6 +3843,31 @@ class LOWindow(object):
self._frame.setComponent(self._container, None) self._frame.setComponent(self._container, None)
return return
def _create_subcontainer(self, ps):
service = 'com.sun.star.awt.ContainerWindowProvider'
cwp = create_instance(service, True)
with get_temp_file() as f:
f.write(self.EMPTY)
f.flush()
subcont = cwp.createContainerWindow(
_path_url(f.name), '', self._container.getPeer(), None)
# ~ service = 'com.sun.star.awt.UnoControlDialog'
# ~ subcont2 = create_instance(service, True)
# ~ service = 'com.sun.star.awt.UnoControlDialogModel'
# ~ model = create_instance(service, True)
# ~ service = 'com.sun.star.awt.UnoControlContainer'
# ~ context = create_instance(service, True)
# ~ subcont2.setModel(model)
# ~ subcont2.setContext(context)
# ~ subcont2.createPeer(self._toolkit, self._container.getPeer())
subcont.setPosSize(0, 0, 500, 500, POSSIZE)
subcont.setVisible(True)
self._container.addControl('subcont', subcont)
self._subcont = subcont
return
def _get_base_control(self, tipo): def _get_base_control(self, tipo):
services = { services = {
'label': 'com.sun.star.awt.UnoControlFixedText', 'label': 'com.sun.star.awt.UnoControlFixedText',
@ -3520,25 +3881,50 @@ class LOWindow(object):
'radio': 'com.sun.star.awt.UnoControlRadioButton', 'radio': 'com.sun.star.awt.UnoControlRadioButton',
'tree': 'com.sun.star.awt.tree.TreeControl', 'tree': 'com.sun.star.awt.tree.TreeControl',
'grid': 'com.sun.star.awt.grid.UnoControlGrid', 'grid': 'com.sun.star.awt.grid.UnoControlGrid',
'tab': 'com.sun.star.awt.tab.UnoControlTabPage',
} }
return services[tipo] return services[tipo]
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'] = _set_image_url(
properties['ImageURL'], self.id_extension)
elif tipo == 'roadmap':
if not 'Height' in properties:
properties['Height'] = self.height
if 'Title' in properties:
properties['Text'] = properties.pop('Title')
elif tipo == 'tab':
if not 'Width' in properties:
properties['Width'] = self.width - 20
if not 'Height' in properties:
properties['Height'] = self.height - 20
return properties
def add_control(self, properties): def add_control(self, properties):
tipo = properties.pop('Type').lower() tipo = properties.pop('Type').lower()
base = self._get_base_control(tipo) root = properties.pop('Root', '')
obj = create_instance(base, True) sheets = properties.pop('Sheets', ())
model = create_instance('{}Model'.format(base), True)
properties = self._special_properties(tipo, properties)
model = self._subcont.Model.createInstance(get_control_model(tipo))
set_properties(model, properties) set_properties(model, properties)
obj.setModel(model)
x = properties.get('X', 5)
y = properties.get('Y', 5)
w = properties.get('Width', 200)
h = properties.get('Height', 25)
obj.setPosSize(x, y, w, h, POSSIZE)
name = properties['Name'] name = properties['Name']
self._container.addControl(name, obj) self._subcont.Model.insertByName(name, model)
add_listeners(self.events, obj, name) control = self._subcont.getControl(name)
control = get_custom_class(tipo, obj) add_listeners(self.events, control, name)
control = get_custom_class(tipo, control)
if tipo == 'tree' and root:
control.root = root
elif tipo == 'tab' and sheets:
control.sheets = sheets
control.events = self.events
setattr(self, name, control) setattr(self, name, control)
return return
@ -3834,8 +4220,12 @@ def json_loads(data):
def get_path_extension(id): def get_path_extension(id):
path = ''
pip = CTX.getValueByName('/singletons/com.sun.star.deployment.PackageInformationProvider') pip = CTX.getValueByName('/singletons/com.sun.star.deployment.PackageInformationProvider')
path = _path_system(pip.getPackageLocation(id)) try:
path = _path_system(pip.getPackageLocation(id))
except Exception as e:
error(e)
return path return path
@ -3979,7 +4369,7 @@ def open_file(path):
if IS_WIN: if IS_WIN:
os.startfile(path) os.startfile(path)
else: else:
subprocess.Popen(['xdg-open', path]) pid = subprocess.Popen(['xdg-open', path]).pid
return return
@ -4032,23 +4422,29 @@ def popen(command, stdin=None):
yield (e.errno, e.strerror) yield (e.errno, e.strerror)
def url_open(url, options={}, json=False): def url_open(url, options={}, verify=True, json=False):
data = '' data = ''
err = ''
req = Request(url) req = Request(url)
try: try:
response = urlopen(req) if verify:
# ~ response.info() response = urlopen(req)
else:
context = ssl._create_unverified_context()
response = urlopen(req, context=context)
except HTTPError as e: except HTTPError as e:
error(e) error(e)
err = str(e)
except URLError as e: except URLError as e:
error(e.reason) error(e.reason)
err = str(e.reason)
else: else:
if json: if json:
data = json_loads(response.read()) data = json_loads(response.read())
else: else:
data = response.read() data = response.read()
return data return data, err
def run(command, wait=False): def run(command, wait=False):
@ -5025,8 +5421,6 @@ class LIBOServer(object):
return instance return instance
# ~ controls = { # ~ controls = {
# ~ 'CheckBox': 'com.sun.star.awt.UnoControlCheckBoxModel', # ~ 'CheckBox': 'com.sun.star.awt.UnoControlCheckBoxModel',
# ~ 'ComboBox': 'com.sun.star.awt.UnoControlComboBoxModel', # ~ 'ComboBox': 'com.sun.star.awt.UnoControlComboBoxModel',

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest:manifest manifest:version="1.2" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"> <manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" manifest:version="1.2">
<manifest:file-entry manifest:full-path="ZAZFavorites.py" manifest:media-type="application/vnd.sun.star.uno-component;type=Python"/> <manifest:file-entry manifest:full-path="ZAZFavorites.py" manifest:media-type="application/vnd.sun.star.uno-component;type=Python"/>
<manifest:file-entry manifest:full-path="Office/Accelerators.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/> <manifest:file-entry manifest:full-path="Office/Accelerators.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>
<manifest:file-entry manifest:full-path="Addons.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/> <manifest:file-entry manifest:full-path="Addons.xcu" manifest:media-type="application/vnd.sun.star.configuration-data"/>

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?> <?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"> <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.Favorites" /> <identifier value="net.elmau.zaz.Favorites" />
<version value="0.4.0" /> <version value="0.5.0" />
<display-name> <display-name>
<name lang="en">Favorites files</name> <name lang="en">Favorites files</name>
<name lang="es">Archivos favoritos</name> <name lang="es">Archivos favoritos</name>

View File

@ -34,6 +34,7 @@ import shlex
import shutil import shutil
import socket import socket
import subprocess import subprocess
import ssl
import sys import sys
import tempfile import tempfile
import threading import threading
@ -41,13 +42,9 @@ import time
import traceback import traceback
import zipfile import zipfile
# ~ from collections import OrderedDict
# ~ from collections.abc import MutableMapping
from functools import wraps from functools import wraps
from operator import itemgetter
from pathlib import Path, PurePath from pathlib import Path, PurePath
from pprint import pprint from pprint import pprint
from enum import IntEnum
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError from urllib.error import URLError, HTTPError
from string import Template from string import Template
@ -91,14 +88,10 @@ from com.sun.star.awt import XMenuListener
from com.sun.star.awt import XKeyListener from com.sun.star.awt import XKeyListener
from com.sun.star.awt import XItemListener from com.sun.star.awt import XItemListener
from com.sun.star.awt import XFocusListener from com.sun.star.awt import XFocusListener
from com.sun.star.awt import XTabListener
from com.sun.star.awt.grid import XGridDataListener
from com.sun.star.awt.grid import XGridSelectionListener
class FontSlant(IntEnum):
NONE = 0
OBLIQUE = 1
ITALIC = 2
DONTKNOW = 3
REVERSE_OBLIQUE = 4
REVERSE_ITALIC = 5
try: try:
from fernet import Fernet, InvalidToken from fernet import Fernet, InvalidToken
@ -119,7 +112,6 @@ KEY = {
SEPARATION = 5 SEPARATION = 5
MSG_LANG = { MSG_LANG = {
'es': { 'es': {
'OK': 'Aceptar', 'OK': 'Aceptar',
@ -130,35 +122,36 @@ MSG_LANG = {
} }
} }
OS = platform.system() OS = platform.system()
USER = getpass.getuser() USER = getpass.getuser()
PC = platform.node() PC = platform.node()
DESKTOP = os.environ.get('DESKTOP_SESSION', '') DESKTOP = os.environ.get('DESKTOP_SESSION', '')
INFO_DEBUG = '{}\n\n{}\n\n{}'.format(sys.version, platform.platform(), '\n'.join(sys.path)) INFO_DEBUG = '{}\n\n{}\n\n{}'.format(sys.version, platform.platform(), '\n'.join(sys.path))
IS_WIN = OS == 'Windows' IS_WIN = OS == 'Windows'
LOG_NAME = 'ZAZ' LOG_NAME = 'ZAZ'
CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16' CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16'
PYTHON = 'python' PYTHON = 'python'
if IS_WIN: if IS_WIN:
PYTHON = 'python.exe' PYTHON = 'python.exe'
CALC = 'calc' CALC = 'calc'
WRITER = 'writer' WRITER = 'writer'
OBJ_CELL = 'ScCellObj' OBJ_CELL = 'ScCellObj'
OBJ_RANGE = 'ScCellRangeObj' OBJ_RANGE = 'ScCellRangeObj'
OBJ_RANGES = 'ScCellRangesObj' OBJ_RANGES = 'ScCellRangesObj'
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES) OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
TEXT_RANGE = 'SwXTextRange'
TEXT_RANGES = 'SwXTextRanges'
TEXT_TYPE_RANGES = (TEXT_RANGE, TEXT_RANGES)
TYPE_DOC = { TYPE_DOC = {
'calc': 'com.sun.star.sheet.SpreadsheetDocument', 'calc': 'com.sun.star.sheet.SpreadsheetDocument',
'writer': 'com.sun.star.text.TextDocument', 'writer': 'com.sun.star.text.TextDocument',
'impress': 'com.sun.star.presentation.PresentationDocument', 'impress': 'com.sun.star.presentation.PresentationDocument',
'draw': 'com.sun.star.drawing.DrawingDocument', 'draw': 'com.sun.star.drawing.DrawingDocument',
# ~ 'base': 'com.sun.star.sdb.OfficeDatabaseDocument',
'base': 'com.sun.star.sdb.DocumentDataSource', 'base': 'com.sun.star.sdb.DocumentDataSource',
'math': 'com.sun.star.formula.FormulaProperties', 'math': 'com.sun.star.formula.FormulaProperties',
'basic': 'com.sun.star.script.BasicIDE', 'basic': 'com.sun.star.script.BasicIDE',
@ -197,19 +190,16 @@ MENUS_WRITER = {
'windows': '.uno:WindowList', 'windows': '.uno:WindowList',
'help': '.uno:HelpMenu', 'help': '.uno:HelpMenu',
} }
MENUS_APP = { MENUS_APP = {
'main': MENUS_MAIN, 'main': MENUS_MAIN,
'calc': MENUS_CALC, 'calc': MENUS_CALC,
'writer': MENUS_WRITER, 'writer': MENUS_WRITER,
} }
EXT = { EXT = {
'pdf': 'pdf', 'pdf': 'pdf',
} }
FILE_NAME_DEBUG = 'debug.odt' FILE_NAME_DEBUG = 'debug.odt'
FILE_NAME_CONFIG = 'zaz-{}.json' FILE_NAME_CONFIG = 'zaz-{}.json'
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
@ -279,6 +269,12 @@ def mri(obj):
return return
def inspect(obj):
zaz = create_instance('net.elmau.zaz.inspect')
zaz.inspect(obj)
return
def catch_exception(f): def catch_exception(f):
@wraps(f) @wraps(f)
def func(*args, **kwargs): def func(*args, **kwargs):
@ -454,12 +450,14 @@ def call_dispatch(url, args=()):
return return
def get_temp_file(): def get_temp_file(only_name=False):
delete = True delete = True
if IS_WIN: if IS_WIN:
delete = False delete = False
return tempfile.NamedTemporaryFile(delete=delete) tmp = tempfile.NamedTemporaryFile(delete=delete)
if only_name:
tmp = tmp.name
return tmp
def _path_url(path): def _path_url(path):
if path.startswith('file://'): if path.startswith('file://'):
@ -501,6 +499,11 @@ def dict_to_property(values, uno_any=False):
return ps return ps
def dict_to_named(values):
ps = tuple([NamedValue(n, v) for n, v in values.items()])
return ps
def property_to_dict(values): def property_to_dict(values):
d = {i.Name: i.Value for i in values} d = {i.Name: i.Value for i in values}
return d return d
@ -934,6 +937,67 @@ class LOCellStyles(object):
return 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): class LOCalc(LODocument):
def __init__(self, obj): def __init__(self, obj):
@ -942,7 +1006,9 @@ class LOCalc(LODocument):
def __getitem__(self, index): def __getitem__(self, index):
if isinstance(index, str): if isinstance(index, str):
index = [s.Name for s in self._sheets if s.CodeName == index][0] or index code_name = [s.Name for s in self._sheets if s.CodeName == index]
if code_name:
index = code_name[0]
return LOCalcSheet(self._sheets[index], self) return LOCalcSheet(self._sheets[index], self)
def __setitem__(self, key, value): def __setitem__(self, key, value):
@ -1182,7 +1248,7 @@ class LOCalcSheet(object):
def _init_values(self): def _init_values(self):
self._events = None self._events = None
self._dp = self.obj.getDrawPage() self._dp = self.obj.getDrawPage()
return self._images = {i.Name: LOImage(i) for i in self._dp}
@property @property
def obj(self): def obj(self):
@ -1192,6 +1258,10 @@ class LOCalcSheet(object):
def doc(self): def doc(self):
return self._doc return self._doc
@property
def images(self):
return self._images
@property @property
def name(self): def name(self):
return self._obj.Name return self._obj.Name
@ -1306,7 +1376,11 @@ class LOWriter(LODocument):
@property @property
def selection(self): def selection(self):
sel = self.obj.getCurrentSelection() sel = self.obj.getCurrentSelection()
return LOTextRange(sel[0]) if sel.ImplementationName == TEXT_RANGES:
return LOTextRange(sel[0])
elif sel.ImplementationName == TEXT_RANGE:
return LOTextRange(sel)
return sel
def write(self, data, cursor=None): def write(self, data, cursor=None):
cursor = cursor or self.selection.cursor.getEnd() cursor = cursor or self.selection.cursor.getEnd()
@ -1583,7 +1657,7 @@ class LODrawImpress(LODocument):
def insert_image(self, path, **kwargs): def insert_image(self, path, **kwargs):
w = kwargs.get('width', 3000) w = kwargs.get('width', 3000)
h = kwargs.get('Height', 1000) h = kwargs.get('Height', 3000)
x = kwargs.get('X', 1000) x = kwargs.get('X', 1000)
y = kwargs.get('Y', 1000) y = kwargs.get('Y', 1000)
@ -1640,6 +1714,9 @@ class LOCellRange(object):
def __getitem__(self, index): def __getitem__(self, index):
return LOCellRange(self.obj[index], self.doc) return LOCellRange(self.obj[index], self.doc)
def __contains__(self, item):
return item.in_range(self)
def _init_values(self): def _init_values(self):
self._type_obj = self.obj.ImplementationName self._type_obj = self.obj.ImplementationName
self._type_content = EMPTY self._type_content = EMPTY
@ -1689,7 +1766,7 @@ class LOCellRange(object):
self.obj.setFormula(data) self.obj.setFormula(data)
else: else:
self.obj.setString(data) self.obj.setString(data)
elif isinstance(data, (int, float)): elif isinstance(data, (int, float, bool)):
self.obj.setValue(data) self.obj.setValue(data)
elif isinstance(data, datetime.datetime): elif isinstance(data, datetime.datetime):
d = data.toordinal() d = data.toordinal()
@ -1707,8 +1784,6 @@ class LOCellRange(object):
return self.obj.getDataArray() return self.obj.getDataArray()
@data.setter @data.setter
def data(self, values): def data(self, values):
if isinstance(values, list):
values = tuple(values)
self.obj.setDataArray(values) self.obj.setDataArray(values)
@property @property
@ -1716,8 +1791,6 @@ class LOCellRange(object):
return self.obj.getFormulaArray() return self.obj.getFormulaArray()
@formula.setter @formula.setter
def formula(self, values): def formula(self, values):
if isinstance(values, list):
values = tuple(values)
self.obj.setFormulaArray(values) self.obj.setFormulaArray(values)
@property @property
@ -1742,13 +1815,19 @@ class LOCellRange(object):
cursor.collapseToSize(cols, rows) cursor.collapseToSize(cols, rows)
return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc) return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc)
def copy_from(self, rango): def copy_from(self, rango, formula=False):
data = rango data = rango
if isinstance(rango, LOCellRange): if isinstance(rango, LOCellRange):
data = rango.data if formula:
data = rango.formula
else:
data = rango.data
rows = len(data) rows = len(data)
cols = len(data[0]) cols = len(data[0])
self.to_size(rows, cols).data = data if formula:
self.to_size(rows, cols).formula = data
else:
self.to_size(rows, cols).data = data
return return
def copy_to(self, cell, formula=False): def copy_to(self, cell, formula=False):
@ -1759,6 +1838,10 @@ class LOCellRange(object):
rango.data = self.data rango.data = self.data
return return
def copy(self, source):
self.sheet.obj.copyRange(self.address, source.range_address)
return
def offset(self, row=1, col=0): def offset(self, row=1, col=0):
ra = self.obj.getRangeAddress() ra = self.obj.getRangeAddress()
col = ra.EndColumn + col col = ra.EndColumn + col
@ -1816,6 +1899,10 @@ class LOCellRange(object):
a = self.obj.getRangeAddressesAsString() a = self.obj.getRangeAddressesAsString()
return a return a
@property
def range_address(self):
return self.obj.getRangeAddress()
@property @property
def current_region(self): def current_region(self):
cursor = self.sheet.get_cursor(self.obj[0,0]) cursor = self.sheet.get_cursor(self.obj[0,0])
@ -1986,6 +2073,10 @@ class EventsListenerBase(unohelper.Base, XEventListener):
self._name = name self._name = name
self._window = window self._window = window
@property
def name(self):
return self._name
def disposing(self, event): def disposing(self, event):
self._controller = None self._controller = None
if not self._window is None: if not self._window is None:
@ -2096,7 +2187,10 @@ class EventsItem(EventsListenerBase, XItemListener):
pass pass
def itemStateChanged(self, event): def itemStateChanged(self, event):
pass event_name = '{}_item_changed'.format(self.name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
class EventsItemRoadmap(EventsItem): class EventsItemRoadmap(EventsItem):
@ -2145,6 +2239,45 @@ class EventsKey(EventsListenerBase, XKeyListener):
return 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 EventsGrid(EventsListenerBase, XGridDataListener, XGridSelectionListener):
def __init__(self, controller, name):
super().__init__(controller, name)
def dataChanged(self, event):
event_name = '{}_data_changed'.format(self.name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
def rowHeadingChanged(self, event):
pass
def rowsInserted(self, event):
pass
def rowsRemoved(self, evemt):
pass
def selectionChanged(self, event):
event_name = '{}_selection_changed'.format(self.name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
class EventsKeyWindow(EventsListenerBase, XKeyListener): class EventsKeyWindow(EventsListenerBase, XKeyListener):
""" """
event.KeyChar event.KeyChar
@ -2221,8 +2354,8 @@ class EventsWindow(EventsListenerBase, XTopWindowListener, XWindowListener):
# ~ XWindowListener # ~ XWindowListener
def windowResized(self, event): def windowResized(self, event):
# ~ sb = self._container.getControl('subcontainer') sb = self._cls._subcont
# ~ sb.setPosSize(0, 0, event.Width, event.Height, SIZE) sb.setPosSize(0, 0, event.Width, event.Height, SIZE)
event_name = '{}_resized'.format(self._name) event_name = '{}_resized'.format(self._name)
if hasattr(self._controller, event_name): if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event) getattr(self._controller, event_name)(event)
@ -2284,6 +2417,7 @@ class UnoBaseObject(object):
@property @property
def parent(self): def parent(self):
ps = self.obj.getContext().PosSize
return self.obj.getContext() return self.obj.getContext()
def _get_possize(self, name): def _get_possize(self, name):
@ -2325,17 +2459,23 @@ class UnoBaseObject(object):
return self._model.Width return self._model.Width
@width.setter @width.setter
def width(self, value): def width(self, value):
self._model.Width = value if hasattr(self.model, 'Width'):
self.model.Width = value
elif hasattr(self.obj, 'PosSize'):
self._set_possize('Width', value)
@property @property
def height(self): def height(self):
if hasattr(self._model, 'Height'): if hasattr(self.model, 'Height'):
return self._model.Height return self.model.Height
ps = self.obj.getPosSize() ps = self.obj.getPosSize()
return ps.Height return ps.Height
@height.setter @height.setter
def height(self, value): def height(self, value):
self._model.Height = value if hasattr(self.model, 'Height'):
self.model.Height = value
elif hasattr(self.obj, 'PosSize'):
self._set_possize('Height', value)
@property @property
def tag(self): def tag(self):
@ -2398,8 +2538,12 @@ class UnoBaseObject(object):
def move(self, origin, x=0, y=5): def move(self, origin, x=0, y=5):
if x: if x:
self.x = origin.x + origin.width + x self.x = origin.x + origin.width + x
else:
self.x = origin.x
if y: if y:
self.y = origin.y + origin.height + y self.y = origin.y + origin.height + y
else:
self.y = origin.y
return return
def possize(self, origin): def possize(self, origin):
@ -2568,16 +2712,19 @@ class UnoGrid(UnoBaseObject):
# ~ def format_columns(self, value): # ~ def format_columns(self, value):
# ~ self._format_columns = value # ~ self._format_columns = value
@property
def value(self):
return self[self.column, self.row]
@property @property
def data(self): def data(self):
return self._data return self._data
@data.setter @data.setter
def data(self, values): def data(self, values):
# ~ self._data = values # ~ self._data = values
self._gdm.removeAllRows() self.clear()
headings = tuple(range(1, len(values) + 1)) headings = tuple(range(1, len(values) + 1))
self._gdm.addRows(headings, values) self._gdm.addRows(headings, values)
# ~ rows = range(grid_dm.RowCount) # ~ rows = range(grid_dm.RowCount)
# ~ colors = [COLORS['GRAY'] if r % 2 else COLORS['WHITE'] for r in rows] # ~ colors = [COLORS['GRAY'] if r % 2 else COLORS['WHITE'] for r in rows]
# ~ grid.Model.RowBackgroundColors = tuple(colors) # ~ grid.Model.RowBackgroundColors = tuple(colors)
@ -2617,6 +2764,10 @@ class UnoGrid(UnoBaseObject):
row.append(d) row.append(d)
return tuple(row) return tuple(row)
def clear(self):
self._gdm.removeAllRows()
return
def add_row(self, data): def add_row(self, data):
# ~ self._data.append(data) # ~ self._data.append(data)
data = self._validate_column(data) data = self._validate_column(data)
@ -2626,18 +2777,17 @@ class UnoGrid(UnoBaseObject):
def remove_row(self, row): def remove_row(self, row):
self._gdm.removeRow(row) self._gdm.removeRow(row)
# ~ del self._data[row] # ~ del self._data[row]
self._update_row_heading() self.update_row_heading()
return return
def _update_row_heading(self): def update_row_heading(self):
for i in range(self.rows): for i in range(self.rows):
self._gdm.updateRowHeading(i, i + 1) self._gdm.updateRowHeading(i, i + 1)
return return
def sort(self, column, asc=True): def sort(self, column, asc=True):
self._gdm.sortByColumn(column, asc) self._gdm.sortByColumn(column, asc)
# ~ self._data.sort(key=itemgetter(column), reverse=not asc) self.update_row_heading()
self._update_row_heading()
return return
def set_column_image(self, column, path): def set_column_image(self, column, path):
@ -2685,7 +2835,6 @@ class UnoRoadmap(UnoBaseObject):
class UnoTree(UnoBaseObject): class UnoTree(UnoBaseObject):
@catch_exception
def __init__(self, obj, ): def __init__(self, obj, ):
super().__init__(obj) super().__init__(obj)
self._tdm = None self._tdm = None
@ -2738,6 +2887,119 @@ class UnoTree(UnoBaseObject):
return return
class UnoTab(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()
@property
def active(self):
return self.current
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'] = _set_column_model(columns)
if not 'Width' in properties:
properties['Width'] = self.width
if not 'Height' in properties:
properties['Height'] = self.height
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): def get_custom_class(tipo, obj):
classes = { classes = {
'label': UnoLabel, 'label': UnoLabel,
@ -2748,7 +3010,7 @@ def get_custom_class(tipo, obj):
'link': UnoLabelLink, 'link': UnoLabelLink,
'roadmap': UnoRoadmap, 'roadmap': UnoRoadmap,
'tree': UnoTree, 'tree': UnoTree,
# ~ 'tab': UnoTab, 'tab': UnoTab,
# ~ 'image': UnoImage, # ~ 'image': UnoImage,
# ~ 'radio': UnoRadio, # ~ 'radio': UnoRadio,
# ~ 'groupbox': UnoGroupBox, # ~ 'groupbox': UnoGroupBox,
@ -2757,6 +3019,24 @@ def get_custom_class(tipo, obj):
return classes[tipo](obj) 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',
'tab': 'com.sun.star.awt.UnoMultiPageModel',
}
return services[control]
def add_listeners(events, control, name=''): def add_listeners(events, control, name=''):
listeners = { listeners = {
'addActionListener': EventsButton, 'addActionListener': EventsButton,
@ -2764,6 +3044,7 @@ def add_listeners(events, control, name=''):
'addItemListener': EventsItem, 'addItemListener': EventsItem,
'addFocusListener': EventsFocus, 'addFocusListener': EventsFocus,
'addKeyListener': EventsKey, 'addKeyListener': EventsKey,
'addTabListener': EventsTab,
} }
if hasattr(control, 'obj'): if hasattr(control, 'obj'):
control = contro.obj control = contro.obj
@ -2785,6 +3066,11 @@ def add_listeners(events, control, name=''):
continue continue
getattr(control, key)(listeners[key](events, name)) getattr(control, key)(listeners[key](events, name))
if is_grid:
controllers = EventsGrid(events, name)
control.addSelectionListener(controllers)
control.Model.GridDataModel.addGridDataListener(controllers)
return return
@ -3174,6 +3460,7 @@ class LOChart(object):
chart_data.setData(data) chart_data.setData(data)
chart_data.RowDescriptions = labels chart_data.RowDescriptions = labels
# ~ Bug
if tipo == 'Pie': if tipo == 'Pie':
chart.setDiagram(chart.createInstance(self.BASE.format('Bar'))) chart.setDiagram(chart.createInstance(self.BASE.format('Bar')))
chart.setDiagram(chart.createInstance(self.BASE.format('Pie'))) chart.setDiagram(chart.createInstance(self.BASE.format('Pie')))
@ -3225,6 +3512,29 @@ class LOChart(object):
return self return self
def _set_column_model(columns):
#~ https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1grid_1_1XGridColumn.html
column_model = create_instance('com.sun.star.awt.grid.DefaultGridColumnModel', True)
for column in columns:
grid_column = create_instance('com.sun.star.awt.grid.GridColumn', True)
for k, v in column.items():
setattr(grid_column, k, v)
column_model.addColumn(grid_column)
return column_model
def _set_image_url(image, id_extension=''):
if exists_path(image):
return _path_url(image)
if not id_extension:
return ''
path = get_path_extension(id_extension)
path = join(path, DIR['images'], image)
return _path_url(path)
class LODialog(object): class LODialog(object):
def __init__(self, **properties): def __init__(self, **properties):
@ -3278,6 +3588,7 @@ class LODialog(object):
'stardiv.Toolkit.UnoButtonControl': 'button', 'stardiv.Toolkit.UnoButtonControl': 'button',
'stardiv.Toolkit.UnoListBoxControl': 'listbox', 'stardiv.Toolkit.UnoListBoxControl': 'listbox',
'stardiv.Toolkit.UnoRoadmapControl': 'roadmap', 'stardiv.Toolkit.UnoRoadmapControl': 'roadmap',
'stardiv.Toolkit.UnoMultiPageControl': 'pages',
} }
return types[name] return types[name]
@ -3375,6 +3686,7 @@ class LODialog(object):
'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel', 'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel',
'image': 'com.sun.star.awt.UnoControlImageControlModel', 'image': 'com.sun.star.awt.UnoControlImageControlModel',
'radio': 'com.sun.star.awt.UnoControlRadioButtonModel', 'radio': 'com.sun.star.awt.UnoControlRadioButtonModel',
'pages': 'com.sun.star.awt.UnoMultiPageModel',
} }
return services[control] return services[control]
@ -3410,11 +3722,18 @@ class LODialog(object):
properties['Height'] = self.height properties['Height'] = self.height
if 'Title' in properties: if 'Title' in properties:
properties['Text'] = properties.pop('Title') properties['Text'] = properties.pop('Title')
elif tipo == 'tab':
if not 'Width' in properties:
properties['Width'] = self.width
if not 'Height' in properties:
properties['Height'] = self.height
return properties return properties
def add_control(self, properties): def add_control(self, properties):
tipo = properties.pop('Type').lower() tipo = properties.pop('Type').lower()
root = properties.pop('Root', '') root = properties.pop('Root', '')
sheets = properties.pop('Sheets', ())
properties = self._special_properties(tipo, properties) properties = self._special_properties(tipo, properties)
model = self.model.createInstance(self._get_control_model(tipo)) model = self.model.createInstance(self._get_control_model(tipo))
@ -3427,6 +3746,9 @@ class LODialog(object):
if tipo == 'tree' and root: if tipo == 'tree' and root:
control.root = root control.root = root
elif tipo == 'pages' and sheets:
control.sheets = sheets
control.events = self.events
setattr(self, name, control) setattr(self, name, control)
return return
@ -3459,13 +3781,26 @@ class LODialog(object):
class LOWindow(object): class LOWindow(object):
EMPTY = b"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dlg:window PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "dialog.dtd">
<dlg:window xmlns:dlg="http://openoffice.org/2000/dialog" xmlns:script="http://openoffice.org/2000/script" dlg:id="empty" dlg:left="0" dlg:top="0" dlg:width="0" dlg:height="0" dlg:closeable="true" dlg:moveable="true" dlg:withtitlebar="false"/>"""
def __init__(self, **kwargs): def __init__(self, **kwargs):
self._events = None self._events = None
self._menu = None self._menu = None
self._container = None self._container = None
self._id_extension = ''
self._obj = self._create(kwargs) self._obj = self._create(kwargs)
@property
def id_extension(self):
return self._id_extension
@id_extension.setter
def id_extension(self, value):
global ID_EXTENSION
ID_EXTENSION = value
self._id_extension = value
def _create(self, properties): def _create(self, properties):
ps = ( ps = (
properties.get('X', 0), properties.get('X', 0),
@ -3476,6 +3811,7 @@ class LOWindow(object):
self._title = properties.get('Title', TITLE) self._title = properties.get('Title', TITLE)
self._create_frame(ps) self._create_frame(ps)
self._create_container(ps) self._create_container(ps)
self._create_subcontainer(ps)
# ~ self._create_splitter(ps) # ~ self._create_splitter(ps)
return return
@ -3507,6 +3843,31 @@ class LOWindow(object):
self._frame.setComponent(self._container, None) self._frame.setComponent(self._container, None)
return return
def _create_subcontainer(self, ps):
service = 'com.sun.star.awt.ContainerWindowProvider'
cwp = create_instance(service, True)
with get_temp_file() as f:
f.write(self.EMPTY)
f.flush()
subcont = cwp.createContainerWindow(
_path_url(f.name), '', self._container.getPeer(), None)
# ~ service = 'com.sun.star.awt.UnoControlDialog'
# ~ subcont2 = create_instance(service, True)
# ~ service = 'com.sun.star.awt.UnoControlDialogModel'
# ~ model = create_instance(service, True)
# ~ service = 'com.sun.star.awt.UnoControlContainer'
# ~ context = create_instance(service, True)
# ~ subcont2.setModel(model)
# ~ subcont2.setContext(context)
# ~ subcont2.createPeer(self._toolkit, self._container.getPeer())
subcont.setPosSize(0, 0, 500, 500, POSSIZE)
subcont.setVisible(True)
self._container.addControl('subcont', subcont)
self._subcont = subcont
return
def _get_base_control(self, tipo): def _get_base_control(self, tipo):
services = { services = {
'label': 'com.sun.star.awt.UnoControlFixedText', 'label': 'com.sun.star.awt.UnoControlFixedText',
@ -3520,25 +3881,50 @@ class LOWindow(object):
'radio': 'com.sun.star.awt.UnoControlRadioButton', 'radio': 'com.sun.star.awt.UnoControlRadioButton',
'tree': 'com.sun.star.awt.tree.TreeControl', 'tree': 'com.sun.star.awt.tree.TreeControl',
'grid': 'com.sun.star.awt.grid.UnoControlGrid', 'grid': 'com.sun.star.awt.grid.UnoControlGrid',
'tab': 'com.sun.star.awt.tab.UnoControlTabPage',
} }
return services[tipo] return services[tipo]
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'] = _set_image_url(
properties['ImageURL'], self.id_extension)
elif tipo == 'roadmap':
if not 'Height' in properties:
properties['Height'] = self.height
if 'Title' in properties:
properties['Text'] = properties.pop('Title')
elif tipo == 'tab':
if not 'Width' in properties:
properties['Width'] = self.width - 20
if not 'Height' in properties:
properties['Height'] = self.height - 20
return properties
def add_control(self, properties): def add_control(self, properties):
tipo = properties.pop('Type').lower() tipo = properties.pop('Type').lower()
base = self._get_base_control(tipo) root = properties.pop('Root', '')
obj = create_instance(base, True) sheets = properties.pop('Sheets', ())
model = create_instance('{}Model'.format(base), True)
properties = self._special_properties(tipo, properties)
model = self._subcont.Model.createInstance(get_control_model(tipo))
set_properties(model, properties) set_properties(model, properties)
obj.setModel(model)
x = properties.get('X', 5)
y = properties.get('Y', 5)
w = properties.get('Width', 200)
h = properties.get('Height', 25)
obj.setPosSize(x, y, w, h, POSSIZE)
name = properties['Name'] name = properties['Name']
self._container.addControl(name, obj) self._subcont.Model.insertByName(name, model)
add_listeners(self.events, obj, name) control = self._subcont.getControl(name)
control = get_custom_class(tipo, obj) add_listeners(self.events, control, name)
control = get_custom_class(tipo, control)
if tipo == 'tree' and root:
control.root = root
elif tipo == 'tab' and sheets:
control.sheets = sheets
control.events = self.events
setattr(self, name, control) setattr(self, name, control)
return return
@ -3834,8 +4220,12 @@ def json_loads(data):
def get_path_extension(id): def get_path_extension(id):
path = ''
pip = CTX.getValueByName('/singletons/com.sun.star.deployment.PackageInformationProvider') pip = CTX.getValueByName('/singletons/com.sun.star.deployment.PackageInformationProvider')
path = _path_system(pip.getPackageLocation(id)) try:
path = _path_system(pip.getPackageLocation(id))
except Exception as e:
error(e)
return path return path
@ -3979,7 +4369,7 @@ def open_file(path):
if IS_WIN: if IS_WIN:
os.startfile(path) os.startfile(path)
else: else:
subprocess.Popen(['xdg-open', path]) pid = subprocess.Popen(['xdg-open', path]).pid
return return
@ -4032,23 +4422,29 @@ def popen(command, stdin=None):
yield (e.errno, e.strerror) yield (e.errno, e.strerror)
def url_open(url, options={}, json=False): def url_open(url, options={}, verify=True, json=False):
data = '' data = ''
err = ''
req = Request(url) req = Request(url)
try: try:
response = urlopen(req) if verify:
# ~ response.info() response = urlopen(req)
else:
context = ssl._create_unverified_context()
response = urlopen(req, context=context)
except HTTPError as e: except HTTPError as e:
error(e) error(e)
err = str(e)
except URLError as e: except URLError as e:
error(e.reason) error(e.reason)
err = str(e.reason)
else: else:
if json: if json:
data = json_loads(response.read()) data = json_loads(response.read())
else: else:
data = response.read() data = response.read()
return data return data, err
def run(command, wait=False): def run(command, wait=False):
@ -5025,8 +5421,6 @@ class LIBOServer(object):
return instance return instance
# ~ controls = { # ~ controls = {
# ~ 'CheckBox': 'com.sun.star.awt.UnoControlCheckBoxModel', # ~ 'CheckBox': 'com.sun.star.awt.UnoControlCheckBoxModel',
# ~ 'ComboBox': 'com.sun.star.awt.UnoControlComboBoxModel', # ~ 'ComboBox': 'com.sun.star.awt.UnoControlComboBoxModel',

60
zaz.py
View File

@ -33,6 +33,7 @@ from xml.dom.minidom import parseString
from conf import ( from conf import (
DATA, DATA,
DIRS, DIRS,
DOMAIN,
EXTENSION, EXTENSION,
FILES, FILES,
INFO, INFO,
@ -138,6 +139,19 @@ def _save(path, data):
return 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(): def _compress_oxt():
log.info('Compress OXT extension...') log.info('Compress OXT extension...')
@ -435,8 +449,50 @@ def _embed(args):
return 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): def main(args):
if args.update:
_update()
return
if args.locales:
_locales(args)
return
if args.embed: if args.embed:
_embed(args) _embed(args)
return return
@ -469,6 +525,10 @@ def _process_command_line_arguments():
default=False, required=False) default=False, required=False)
parser.add_argument('-d', '--document', dest='document', default='') parser.add_argument('-d', '--document', dest='document', default='')
parser.add_argument('-f', '--files', dest='files', 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() return parser.parse_args()