diff --git a/CHANGELOG b/CHANGELOG index c03539d..d83bb2a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,13 @@ +v 0.3.0 [12-nov-2019] + - Update easymacro.py + - Test install numpy + + +v 0.2.0 [18-oct-2019] +--------------------- + - Add spanish + + v 0.1.0 [18-oct-2019] --------------------- - Initial version diff --git a/VERSION b/VERSION index 5faa42c..69367fd 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -0.2.0 +0.3.0 diff --git a/conf.py b/conf.py index f1685e9..3643ab8 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ import logging TYPE_EXTENSION = 1 # ~ https://semver.org/ -VERSION = '0.2.0' +VERSION = '0.3.0' # ~ Your great extension name, not used spaces NAME = 'ZAZPip' diff --git a/easymacro.py b/easymacro.py index a990a24..8e8e604 100644 --- a/easymacro.py +++ b/easymacro.py @@ -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 Enum, IntEnum from urllib.request import Request, urlopen from urllib.error import URLError, HTTPError from string import Template @@ -96,15 +93,6 @@ 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 except ImportError: @@ -124,7 +112,6 @@ KEY = { SEPARATION = 5 - MSG_LANG = { 'es': { 'OK': 'Aceptar', @@ -135,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', @@ -202,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' @@ -284,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): @@ -1008,7 +999,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): @@ -1376,7 +1369,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() @@ -1710,6 +1707,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 @@ -1759,7 +1759,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() @@ -1777,8 +1777,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 @@ -1786,8 +1784,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 @@ -1812,13 +1808,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): @@ -2178,7 +2180,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): @@ -2447,23 +2452,23 @@ class UnoBaseObject(object): return self._model.Width @width.setter def width(self, value): - if hasattr(self.obj, 'PosSize'): + if hasattr(self.model, 'Width'): + self.model.Width = value + elif hasattr(self.obj, 'PosSize'): self._set_possize('Width', value) - else: - self._model.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): - if hasattr(self.obj, 'PosSize'): + if hasattr(self.model, 'Height'): + self.model.Height = value + elif hasattr(self.obj, 'PosSize'): self._set_possize('Height', value) - else: - self._model.Height = value @property def tag(self): @@ -2526,8 +2531,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): @@ -2771,7 +2780,6 @@ 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() return @@ -3022,7 +3030,6 @@ def get_control_model(control): return services[control] -@catch_exception def add_listeners(events, control, name=''): listeners = { 'addActionListener': EventsButton, @@ -3446,6 +3453,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'))) @@ -3890,7 +3898,6 @@ class LOWindow(object): return properties - @catch_exception def add_control(self, properties): tipo = properties.pop('Type').lower() root = properties.pop('Root', '') @@ -4404,23 +4411,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): @@ -5397,8 +5410,6 @@ class LIBOServer(object): return instance - - # ~ controls = { # ~ 'CheckBox': 'com.sun.star.awt.UnoControlCheckBoxModel', # ~ 'ComboBox': 'com.sun.star.awt.UnoControlComboBoxModel', diff --git a/files/ZAZPip_v0.1.0.oxt b/files/ZAZPip_v0.1.0.oxt deleted file mode 100644 index 554b948..0000000 Binary files a/files/ZAZPip_v0.1.0.oxt and /dev/null differ diff --git a/files/ZAZPip_v0.2.0.oxt b/files/ZAZPip_v0.3.0.oxt similarity index 52% rename from files/ZAZPip_v0.2.0.oxt rename to files/ZAZPip_v0.3.0.oxt index e087f5d..e412bc5 100644 Binary files a/files/ZAZPip_v0.2.0.oxt and b/files/ZAZPip_v0.3.0.oxt differ diff --git a/source/ZAZPip.py b/source/ZAZPip.py index 8cbfacb..6473f17 100644 --- a/source/ZAZPip.py +++ b/source/ZAZPip.py @@ -16,6 +16,7 @@ PIP = 'pip' PACKAGES = { 'psycopg2-binary': 'ok.png', 'peewee': 'ok.png', + 'numpy': 'ok.png', } @@ -62,10 +63,10 @@ class Controllers(object): path_pip = f.name self.d.lst_log.insert('Download PIP...') - data = app.url_open(URL_PIP) - if not data: + data, err = app.url_open(URL_PIP, verify=False) + if err: msg = _('Do you have internet connection?') - app.errorbox(msg) + app.errorbox('{}\n\n{}'.format(msg, err)) return app.save_file(path_pip, 'wb', data) @@ -486,13 +487,13 @@ class ZAZPip(unohelper.Base, XJobExecutor): controls = (dialog.cmd_home, dialog.cmd_search, dialog.cmd_uninstall, dialog.cmd_shell) - dialog.center(controls) + dialog.lbl_package.move(dialog.cmd_home) + dialog.txt_search.move(dialog.lbl_package) + dialog.lst_package.move(dialog.txt_search) dialog.lbl_package.center() dialog.lst_package.center() dialog.txt_search.center() - dialog.lbl_package.move(dialog.cmd_search) - dialog.txt_search.move(dialog.lbl_package) - dialog.lst_package.move(dialog.txt_search) + dialog.center(controls) dialog.step = 10 diff --git a/source/description.xml b/source/description.xml index 66dbf0a..015d124 100644 --- a/source/description.xml +++ b/source/description.xml @@ -1,7 +1,7 @@ - + ZAZ Pip ZAZ Pip diff --git a/source/pythonpath/easymacro.py b/source/pythonpath/easymacro.py index 39a2a79..8e8e604 100644 --- a/source/pythonpath/easymacro.py +++ b/source/pythonpath/easymacro.py @@ -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 @@ -92,14 +89,9 @@ 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 @@ -120,7 +112,6 @@ KEY = { SEPARATION = 5 - MSG_LANG = { 'es': { 'OK': 'Aceptar', @@ -131,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', @@ -198,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' @@ -280,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): @@ -1004,7 +999,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): @@ -1372,7 +1369,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() @@ -1706,6 +1707,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 @@ -1755,7 +1759,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() @@ -1773,8 +1777,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 @@ -1782,8 +1784,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 @@ -1808,13 +1808,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): @@ -2060,6 +2066,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: @@ -2170,7 +2180,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): @@ -2231,6 +2244,33 @@ class EventsTab(EventsListenerBase, XTabListener): 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 @@ -2307,8 +2347,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) @@ -2370,6 +2410,7 @@ class UnoBaseObject(object): @property def parent(self): + ps = self.obj.getContext().PosSize return self.obj.getContext() def _get_possize(self, name): @@ -2411,17 +2452,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): @@ -2484,8 +2531,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): @@ -2654,16 +2705,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) @@ -2703,6 +2757,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) @@ -2712,18 +2770,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): @@ -2823,7 +2880,7 @@ class UnoTree(UnoBaseObject): return -class UnoPages(UnoBaseObject): +class UnoTab(UnoBaseObject): def __init__(self, obj): super().__init__(obj) @@ -2835,6 +2892,9 @@ class UnoPages(UnoBaseObject): @property def current(self): return self.obj.getActiveTabID() + @property + def active(self): + return self.current def get_sheet(self, id): if isinstance(id, int): @@ -2887,7 +2947,11 @@ class UnoPages(UnoBaseObject): def _special_properties(self, tipo, properties): columns = properties.pop('Columns', ()) if tipo == 'grid': - properties['ColumnModel'] = self._set_column_model(columns) + 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': @@ -2939,7 +3003,7 @@ def get_custom_class(tipo, obj): 'link': UnoLabelLink, 'roadmap': UnoRoadmap, 'tree': UnoTree, - 'pages': UnoPages, + 'tab': UnoTab, # ~ 'image': UnoImage, # ~ 'radio': UnoRadio, # ~ 'groupbox': UnoGroupBox, @@ -2961,7 +3025,7 @@ def get_control_model(control): 'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel', 'image': 'com.sun.star.awt.UnoControlImageControlModel', 'radio': 'com.sun.star.awt.UnoControlRadioButtonModel', - 'pages': 'com.sun.star.awt.UnoMultiPageModel', + 'tab': 'com.sun.star.awt.UnoMultiPageModel', } return services[control] @@ -2995,6 +3059,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 @@ -3384,6 +3453,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'))) @@ -3435,6 +3505,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): @@ -3622,7 +3715,7 @@ class LODialog(object): properties['Height'] = self.height if 'Title' in properties: properties['Text'] = properties.pop('Title') - elif tipo == 'pages': + elif tipo == 'tab': if not 'Width' in properties: properties['Width'] = self.width if not 'Height' in properties: @@ -3681,13 +3774,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), @@ -3698,6 +3804,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 @@ -3729,6 +3836,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', @@ -3742,25 +3874,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 @@ -4201,7 +4358,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 @@ -4254,23 +4411,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): @@ -5247,8 +5410,6 @@ class LIBOServer(object): return instance - - # ~ controls = { # ~ 'CheckBox': 'com.sun.star.awt.UnoControlCheckBoxModel', # ~ 'ComboBox': 'com.sun.star.awt.UnoControlComboBoxModel',