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]
- Fix error in main

View File

@ -9,11 +9,12 @@ https://gitlab.com/mauriciobaeza/zaz
### Software libre, no gratis
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

View File

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

View File

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

View File

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

View File

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

View File

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

60
zaz.py
View File

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