Add support for Windows

This commit is contained in:
Mauricio Baeza 2019-10-29 11:23:24 -06:00
parent 264dce2449
commit 1cdd526ac7
15 changed files with 406 additions and 30 deletions

View File

@ -1,5 +1,7 @@
v 0.10.0 [21-oct-2019]
- Add suuport for tree control
v 0.10.0 [29-oct-2019]
- Add support for tree control
- Add support for Windows
- Add support for Tabs
v 0.9.0 [19-oct-2019]

View File

@ -1,7 +1,7 @@
* Used zaz and easymacro
* Report errors
* Add examples
* Add to list of proyects develop with zaz or easymacro
* Add to project in the list of develop with zaz or easymacro
* Send me a postal card
* Pay for support

View File

@ -27,3 +27,5 @@ PayPal :( donate ATT elmau DOT net
* https://gitlab.com/mauriciobaeza/zaz-barcode
* https://gitlab.com/mauriciobaeza/zaz-favorite
* https://gitlab.com/mauriciobaeza/zaz-easymacro
* https://gitlab.com/mauriciobaeza/zaz-pip
* https://gitlab.com/mauriciobaeza/zaz-inspect

View File

@ -1 +1 @@
0.9.0
0.10.0

View File

@ -47,7 +47,7 @@ from functools import wraps
from operator import itemgetter
from pathlib import Path, PurePath
from pprint import pprint
from enum import IntEnum
from enum import Enum, IntEnum
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
from string import Template
@ -91,6 +91,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
@ -100,6 +104,7 @@ class FontSlant(IntEnum):
REVERSE_OBLIQUE = 4
REVERSE_ITALIC = 5
try:
from fernet import Fernet, InvalidToken
except ImportError:
@ -934,6 +939,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):
@ -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
@ -1759,6 +1829,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 +1890,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 +2064,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:
@ -2145,6 +2227,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 +2342,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 +2405,7 @@ class UnoBaseObject(object):
@property
def parent(self):
ps = self.obj.getContext().PosSize
return self.obj.getContext()
def _get_possize(self, name):
@ -2325,7 +2447,10 @@ class UnoBaseObject(object):
return self._model.Width
@width.setter
def width(self, value):
self._model.Width = value
if hasattr(self.obj, 'PosSize'):
self._set_possize('Width', value)
else:
self._model.Width = value
@property
def height(self):
@ -2335,7 +2460,10 @@ class UnoBaseObject(object):
return ps.Height
@height.setter
def height(self, value):
self._model.Height = value
if hasattr(self.obj, 'PosSize'):
self._set_possize('Height', value)
else:
self._model.Height = value
@property
def tag(self):
@ -2568,16 +2696,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 +2748,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,10 +2761,10 @@ 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
@ -2637,7 +2772,7 @@ class UnoGrid(UnoBaseObject):
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 +2820,6 @@ class UnoRoadmap(UnoBaseObject):
class UnoTree(UnoBaseObject):
@catch_exception
def __init__(self, obj, ):
super().__init__(obj)
self._tdm = None
@ -2738,6 +2872,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 +2995,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 +3004,25 @@ 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]
@catch_exception
def add_listeners(events, control, name=''):
listeners = {
'addActionListener': EventsButton,
@ -2764,6 +3030,7 @@ def add_listeners(events, control, name=''):
'addItemListener': EventsItem,
'addFocusListener': EventsFocus,
'addKeyListener': EventsKey,
'addTabListener': EventsTab,
}
if hasattr(control, 'obj'):
control = contro.obj
@ -2785,6 +3052,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
@ -3225,6 +3497,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 +3573,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 +3671,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 +3707,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 +3731,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 +3766,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 +3796,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 +3828,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 +3866,51 @@ 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
@catch_exception
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
@ -3979,7 +4351,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

BIN
source/images/api.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
source/images/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

BIN
source/images/cancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 517 B

View File

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 245 B

BIN
source/images/first.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
source/images/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

BIN
source/images/last.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
source/images/next.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
source/images/remove.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

BIN
source/images/update.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B