diff --git a/CHANGELOG b/CHANGELOG index 0ad42bb..47b7c04 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +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] - Add support for generate locales - Start support for forms diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 25ce94a..d18060f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 diff --git a/README.md b/README.md index 826e6b8..f45ef3b 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/VERSION b/VERSION index ac39a10..78bc1ab 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.9.0 +0.10.0 diff --git a/source/easymacro.py b/source/easymacro.py index 8f9f5b9..4762bb3 100644 --- a/source/easymacro.py +++ b/source/easymacro.py @@ -41,12 +41,13 @@ import time import traceback import zipfile -from collections import OrderedDict -from collections.abc import MutableMapping +# ~ 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 Enum, IntEnum from urllib.request import Request, urlopen from urllib.error import URLError, HTTPError from string import Template @@ -90,6 +91,18 @@ 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: @@ -336,18 +349,17 @@ def run_in_thread(fn): return run -def now(): - return datetime.datetime.now() +def now(only_time=False): + now = datetime.datetime.now() + if only_time: + return now.time() + return now def today(): return datetime.date.today() -def time(): - return datetime.datetime.now().time() - - def get_date(year, month, day, hour=-1, minute=-1, second=-1): if hour > -1 or minute > -1 or second > -1: h = hour @@ -600,9 +612,6 @@ class LODocument(object): def _init_values(self): self._type_doc = get_type_doc(self.obj) - # ~ if self._type_doc == 'base': - # ~ self._cc = self.obj.DatabaseDocument.getCurrentController() - # ~ else: self._cc = self.obj.getCurrentController() return @@ -930,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): @@ -1178,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): @@ -1188,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 @@ -1364,6 +1438,42 @@ class LOWriter(LODocument): self._cc.select(text) return + def search(self, options): + descriptor = self.obj.createSearchDescriptor() + descriptor.setSearchString(options.get('Search', '')) + descriptor.SearchCaseSensitive = options.get('CaseSensitive', False) + descriptor.SearchWords = options.get('Words', False) + if 'Attributes' in options: + attr = dict_to_property(options['Attributes']) + descriptor.setSearchAttributes(attr) + if hasattr(descriptor, 'SearchRegularExpression'): + descriptor.SearchRegularExpression = options.get('RegularExpression', False) + if hasattr(descriptor, 'SearchType') and 'Type' in options: + descriptor.SearchType = options['Type'] + + if options.get('First', False): + found = self.obj.findFirst(descriptor) + else: + found = self.obj.findAll(descriptor) + + return found + + def replace(self, options): + descriptor = self.obj.createReplaceDescriptor() + descriptor.setSearchString(options['Search']) + descriptor.setReplaceString(options['Replace']) + descriptor.SearchCaseSensitive = options.get('CaseSensitive', False) + descriptor.SearchWords = options.get('Words', False) + if 'Attributes' in options: + attr = dict_to_property(options['Attributes']) + descriptor.setSearchAttributes(attr) + if hasattr(descriptor, 'SearchRegularExpression'): + descriptor.SearchRegularExpression = options.get('RegularExpression', False) + if hasattr(descriptor, 'SearchType') and 'Type' in options: + descriptor.SearchType = options['Type'] + found = self.obj.replaceAll(descriptor) + return found + class LOTextRange(object): @@ -1719,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 @@ -1776,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]) @@ -1908,6 +2026,36 @@ class LOCellRange(object): chart.cell = self return chart + def search(self, options): + descriptor = self.obj.Spreadsheet.createSearchDescriptor() + descriptor.setSearchString(options.get('Search', '')) + descriptor.SearchCaseSensitive = options.get('CaseSensitive', False) + descriptor.SearchWords = options.get('Words', False) + if hasattr(descriptor, 'SearchRegularExpression'): + descriptor.SearchRegularExpression = options.get('RegularExpression', False) + if hasattr(descriptor, 'SearchType') and 'Type' in options: + descriptor.SearchType = options['Type'] + + if options.get('First', False): + found = self.obj.findFirst(descriptor) + else: + found = self.obj.findAll(descriptor) + + return found + + def replace(self, options): + descriptor = self.obj.Spreadsheet.createReplaceDescriptor() + descriptor.setSearchString(options['Search']) + descriptor.setReplaceString(options['Replace']) + descriptor.SearchCaseSensitive = options.get('CaseSensitive', False) + descriptor.SearchWords = options.get('Words', False) + if hasattr(descriptor, 'SearchRegularExpression'): + descriptor.SearchRegularExpression = options.get('RegularExpression', False) + if hasattr(descriptor, 'SearchType') and 'Type' in options: + descriptor.SearchType = options['Type'] + found = self.obj.replaceAll(descriptor) + return found + class EventsListenerBase(unohelper.Base, XEventListener): @@ -1916,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: @@ -2075,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 @@ -2151,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) @@ -2214,6 +2405,7 @@ class UnoBaseObject(object): @property def parent(self): + ps = self.obj.getContext().PosSize return self.obj.getContext() def _get_possize(self, name): @@ -2255,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): @@ -2265,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): @@ -2416,7 +2614,7 @@ class UnoListBox(UnoBaseObject): @property def value(self): - return self.obj.SelectedItem + return self.obj.getSelectedItem() @property def count(self): @@ -2430,6 +2628,10 @@ class UnoListBox(UnoBaseObject): self.model.StringItemList = list(sorted(values)) return + def unselect(self): + self.obj.selectItem(self.value, False) + return + def select(self, pos=0): if isinstance(pos, str): self.obj.selectItem(pos, True) @@ -2438,7 +2640,7 @@ class UnoListBox(UnoBaseObject): return def clear(self): - self.obj.removeItems(0, self.count) + self.model.removeAllItems() return def _set_image_url(self, image): @@ -2494,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) @@ -2543,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) @@ -2552,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 @@ -2563,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): @@ -2609,6 +2818,173 @@ class UnoRoadmap(UnoBaseObject): return +class UnoTree(UnoBaseObject): + + def __init__(self, obj, ): + super().__init__(obj) + self._tdm = None + self._data = [] + + @property + def selection(self): + return self.obj.Selection + + @property + def root(self): + if self._tdm is None: + return '' + return self._tdm.Root.DisplayValue + + @root.setter + def root(self, value): + self._add_data_model(value) + + def _add_data_model(self, name): + tdm = create_instance('com.sun.star.awt.tree.MutableTreeDataModel') + root = tdm.createNode(name, True) + root.DataValue = 0 + tdm.setRoot(root) + self.model.DataModel = tdm + self._tdm = self.model.DataModel + self._add_data() + return + + @property + def data(self): + return self._data + @data.setter + def data(self, values): + self._data = list(values) + self._add_data() + + def _add_data(self): + if not self.data: + return + + parents = {} + for node in self.data: + parent = parents.get(node[1], self._tdm.Root) + child = self._tdm.createNode(node[2], False) + child.DataValue = node[0] + parent.appendChild(child) + parents[node[0]] = child + self.obj.expandNode(self._tdm.Root) + 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, @@ -2618,16 +2994,35 @@ def get_custom_class(tipo, obj): 'grid': UnoGrid, 'link': UnoLabelLink, 'roadmap': UnoRoadmap, - # ~ 'tab': UnoTab, + 'tree': UnoTree, + 'tab': UnoTab, # ~ 'image': UnoImage, # ~ 'radio': UnoRadio, # ~ 'groupbox': UnoGroupBox, - # ~ 'tree': UnoTree, 'formbutton': FormButton, } 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, @@ -2635,6 +3030,7 @@ def add_listeners(events, control, name=''): 'addItemListener': EventsItem, 'addFocusListener': EventsFocus, 'addKeyListener': EventsKey, + 'addTabListener': EventsTab, } if hasattr(control, 'obj'): control = contro.obj @@ -2656,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 @@ -3045,6 +3446,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'))) @@ -3096,6 +3498,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): @@ -3144,11 +3569,12 @@ class LODialog(object): def _get_type_control(self, name): types = { 'stardiv.Toolkit.UnoFixedTextControl': 'label', - 'stardiv.Toolkit.UnoButtonControl': 'button', - 'stardiv.Toolkit.UnoEditControl': 'text', - 'stardiv.Toolkit.UnoRoadmapControl': 'roadmap', 'stardiv.Toolkit.UnoFixedHyperlinkControl': 'link', + 'stardiv.Toolkit.UnoEditControl': 'text', + 'stardiv.Toolkit.UnoButtonControl': 'button', 'stardiv.Toolkit.UnoListBoxControl': 'listbox', + 'stardiv.Toolkit.UnoRoadmapControl': 'roadmap', + 'stardiv.Toolkit.UnoMultiPageControl': 'pages', } return types[name] @@ -3235,17 +3661,18 @@ class LODialog(object): def _get_control_model(self, control): services = { - 'button': 'com.sun.star.awt.UnoControlButtonModel', - 'grid': 'com.sun.star.awt.grid.UnoControlGridModel', - 'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel', - 'image': 'com.sun.star.awt.UnoControlImageControlModel', 'label': 'com.sun.star.awt.UnoControlFixedTextModel', 'link': 'com.sun.star.awt.UnoControlFixedHyperlinkModel', - 'listbox': 'com.sun.star.awt.UnoControlListBoxModel', - 'radio': 'com.sun.star.awt.UnoControlRadioButtonModel', - 'roadmap': 'com.sun.star.awt.UnoControlRoadmapModel', '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', + 'pages': 'com.sun.star.awt.UnoMultiPageModel', } return services[control] @@ -3281,10 +3708,19 @@ 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)) set_properties(model, properties) @@ -3293,6 +3729,13 @@ class LODialog(object): control = self.obj.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 + control.events = self.events + setattr(self, name, control) return @@ -3324,13 +3767,26 @@ class LODialog(object): class LOWindow(object): + EMPTY = b""" + +""" 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), @@ -3341,6 +3797,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 @@ -3372,6 +3829,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', @@ -3385,25 +3867,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 @@ -3511,7 +4019,7 @@ def get_document(title=''): return doc for d in desktop.getComponents(): - if d.Title == title: + if hasattr(d, 'Title') and d.Title == title: doc = d break @@ -3704,6 +4212,10 @@ def get_path_extension(id): return path +def get_home(): + return Path.home() + + # ~ Export ok def inputbox(message, default='', title=TITLE, echochar=''): @@ -3840,7 +4352,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 @@ -3898,6 +4410,7 @@ def url_open(url, options={}, json=False): req = Request(url) try: response = urlopen(req) + # ~ response.info() except HTTPError as e: error(e) except URLError as e: diff --git a/source/images/api.png b/source/images/api.png new file mode 100644 index 0000000..7b6e33f Binary files /dev/null and b/source/images/api.png differ diff --git a/source/images/back.png b/source/images/back.png new file mode 100644 index 0000000..71dd8d0 Binary files /dev/null and b/source/images/back.png differ diff --git a/source/images/cancel.png b/source/images/cancel.png new file mode 100644 index 0000000..934938d Binary files /dev/null and b/source/images/cancel.png differ diff --git a/source/images/console-24.png b/source/images/console.png similarity index 100% rename from source/images/console-24.png rename to source/images/console.png diff --git a/source/images/first.png b/source/images/first.png new file mode 100644 index 0000000..d196345 Binary files /dev/null and b/source/images/first.png differ diff --git a/source/images/home.png b/source/images/home.png new file mode 100644 index 0000000..421ca34 Binary files /dev/null and b/source/images/home.png differ diff --git a/source/images/last.png b/source/images/last.png new file mode 100644 index 0000000..fb0ce63 Binary files /dev/null and b/source/images/last.png differ diff --git a/source/images/next.png b/source/images/next.png new file mode 100644 index 0000000..0769ade Binary files /dev/null and b/source/images/next.png differ diff --git a/source/images/record.png b/source/images/record.png new file mode 100644 index 0000000..30eb005 Binary files /dev/null and b/source/images/record.png differ diff --git a/source/images/remove.png b/source/images/remove.png new file mode 100644 index 0000000..097c3fa Binary files /dev/null and b/source/images/remove.png differ diff --git a/source/images/stop.png b/source/images/stop.png new file mode 100644 index 0000000..527571a Binary files /dev/null and b/source/images/stop.png differ diff --git a/source/images/update.png b/source/images/update.png new file mode 100644 index 0000000..496c72c Binary files /dev/null and b/source/images/update.png differ