# ~ FILTER_PDF = '/org.openoffice.Office.Common/Filter/PDF/Export/' class LODocument(object): def __init__(self, obj): self._obj = obj self._init_values() def _init_values(self): self._type_doc = get_type_doc(self.obj) self._cc = self.obj.getCurrentController() return @property def obj(self): return self._obj @property def title(self): return self.obj.getTitle() @title.setter def title(self, value): self.obj.setTitle(value) @property def uid(self): return self.obj.RuntimeUID @property def type(self): return self._type_doc @property def frame(self): return self._cc.getFrame() @property def is_saved(self): return self.obj.hasLocation() @property def is_modified(self): return self.obj.isModified() @property def is_read_only(self): return self.obj.isReadOnly() @property def path(self): return _path_system(self.obj.getURL()) @property def statusbar(self): return self._cc.getStatusIndicator() @property def visible(self): w = self._cc.getFrame().getContainerWindow() return w.isVisible() @visible.setter def visible(self, value): w = self._cc.getFrame().getContainerWindow() w.setVisible(value) @property def zoom(self): return self._cc.ZoomValue @zoom.setter def zoom(self, value): self._cc.ZoomValue = value @property def table_auto_formats(self): taf = create_instance('com.sun.star.sheet.TableAutoFormats') return taf.ElementNames def create_instance(self, name): obj = self.obj.createInstance(name) return obj def save(self, path='', **kwargs): # ~ opt = _properties(kwargs) opt = dict_to_property(kwargs) if path: self._obj.storeAsURL(_path_url(path), opt) else: self._obj.store() return True def close(self): self.obj.close(True) return def focus(self): w = self._cc.getFrame().getComponentWindow() w.setFocus() return def paste(self): sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard') transferable = sc.getContents() self._cc.insertTransferable(transferable) return self.obj.getCurrentSelection() def to_pdf(self, path, **kwargs): path_pdf = path if path: if is_dir(path): _, _, n, _ = get_info_path(self.path) path_pdf = join(path, '{}.{}'.format(n, EXT['pdf'])) else: path_pdf = replace_ext(self.path, EXT['pdf']) filter_name = '{}_pdf_Export'.format(self.type) filter_data = dict_to_property(kwargs, True) args = { 'FilterName': filter_name, 'FilterData': filter_data, } args = dict_to_property(args) try: self.obj.storeToURL(_path_url(path_pdf), args) except Exception as e: error(e) path_pdf = '' return path_pdf # ~ If location="document" Then # ~ sp = ThisComponent.getScriptProvider() class FormControlBase(object): EVENTS = { 'action': 'actionPerformed', 'click': 'mousePressed', } TYPES = { 'actionPerformed': 'XActionListener', 'mousePressed': 'XMouseListener', } def __init__(self, obj): self._obj = obj self._index = -1 self._rules = {} @property def obj(self): return self._obj @property def name(self): return self.obj.Name @property def form(self): return self.obj.getParent() @property def index(self): return self._index @index.setter def index(self, value): self._index = value @property def events(self): return self.form.getScriptEvents(self.index) def remove_event(self, name=''): for ev in self.events: if name and \ ev.EventMethod == self.EVENTS[name] and \ ev.ListenerType == self.TYPES[ev.EventMethod]: self.form.revokeScriptEvent(self.index, ev.ListenerType, ev.EventMethod, ev.AddListenerParam) break else: self.form.revokeScriptEvent(self.index, ev.ListenerType, ev.EventMethod, ev.AddListenerParam) return def add_event(self, name, macro): if not 'name' in macro: macro['name'] = '{}_{}'.format(self.name, name) event = ScriptEventDescriptor() event.AddListenerParam = '' event.EventMethod = self.EVENTS[name] event.ListenerType = self.TYPES[event.EventMethod] event.ScriptCode = _get_url_script(macro) event.ScriptType = 'Script' for ev in self.events: if ev.EventMethod == event.EventMethod and \ ev.ListenerType == event.ListenerType: self.form.revokeScriptEvent(self.index, event.ListenerType, event.EventMethod, event.AddListenerParam) break self.form.registerScriptEvent(self.index, event) return class FormButton(FormControlBase): def __init__(self, obj): super().__init__(obj) class LOForm(ObjectBase): def __init__(self, obj): super().__init__(obj) self._init_controls() def __getitem__(self, index): if isinstance(index, int): return self._controls[index] else: return getattr(self, index) def _get_type_control(self, name): types = { # ~ 'stardiv.Toolkit.UnoFixedTextControl': 'label', 'com.sun.star.form.OButtonModel': 'formbutton', # ~ 'stardiv.Toolkit.UnoEditControl': 'text', # ~ 'stardiv.Toolkit.UnoRoadmapControl': 'roadmap', # ~ 'stardiv.Toolkit.UnoFixedHyperlinkControl': 'link', # ~ 'stardiv.Toolkit.UnoListBoxControl': 'listbox', } return types[name] def _init_controls(self): self._controls = [] for i, c in enumerate(self.obj.ControlModels): tipo = self._get_type_control(c.ImplementationName) control = get_custom_class(tipo, c) control.index = i self._controls.append(control) setattr(self, c.Name, control) @property def name(self): return self._obj.getName() @name.setter def name(self, value): self._obj.setName(value) class LOForms(ObjectBase): def __init__(self, obj, doc): self._doc = doc super().__init__(obj) def __getitem__(self, index): form = super().__getitem__(index) return LOForm(form) @property def doc(self): return self._doc @property def count(self): return self.obj.getCount() @property def names(self): return self.obj.getElementNames() def exists(self, name): return name in self.names def insert(self, name): form = self.doc.create_instance('com.sun.star.form.component.Form') self.obj.insertByName(name, form) return self[name] def remove(self, index): if isinstance(index, int): self.obj.removeByIndex(index) else: self.obj.removeByName(index) return class LOCellStyle(LOObjectBase): def __init__(self, obj): super().__init__(obj) @property def name(self): return self.obj.Name def apply(self, properties): set_properties(self.obj, properties) return class LOCellStyles(object): def __init__(self, obj): self._obj = obj def __len__(self): return len(self.obj) def __getitem__(self, index): return LOCellStyle(self.obj[index]) def __setitem__(self, key, value): self.obj[key] = value def __delitem__(self, key): if not isinstance(key, str): key = key.Name del self.obj[key] def __contains__(self, item): return item in self.obj @property def obj(self): return self._obj @property def names(self): return self.obj.ElementNames def apply(self, style, properties): set_properties(style, properties) return class LOImage(object): TYPES = { 'image/png': 'png', 'image/jpeg': 'jpg', } def __init__(self, obj): self._obj = obj @property def address(self): return self.obj.Anchor.AbsoluteName @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): super().__init__(obj) self._sheets = obj.getSheets() def __getitem__(self, index): if isinstance(index, str): 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): self._sheets[key] = value def __contains__(self, item): return item in self.obj.Sheets @property def headers(self): return self._cc.ColumnRowHeaders @headers.setter def headers(self, value): self._cc.ColumnRowHeaders = value @property def tabs(self): return self._cc.SheetTabs @tabs.setter def tabs(self, value): self._cc.SheetTabs = value @property def active(self): return LOCalcSheet(self._cc.getActiveSheet(), self) def activate(self, sheet): obj = sheet if isinstance(sheet, LOCalcSheet): obj = sheet.obj elif isinstance(sheet, str): obj = self[sheet].obj self._cc.setActiveSheet(obj) return @property def selection(self): sel = self.obj.getCurrentSelection() if sel.ImplementationName in OBJ_TYPE_RANGES: sel = LOCellRange(sel, self) return sel @property def sheets(self): return LOCalcSheets(self._sheets, self) @property def names(self): return self.sheets.names @property def cell_style(self): obj = self.obj.getStyleFamilies()['CellStyles'] return LOCellStyles(obj) def create(self): return self.obj.createInstance('com.sun.star.sheet.Spreadsheet') def insert(self, name, pos=-1): # ~ sheet = obj.createInstance('com.sun.star.sheet.Spreadsheet') # ~ obj.Sheets['New'] = sheet index = pos if pos < 0: index = self._sheets.Count + pos + 1 if isinstance(name, str): self._sheets.insertNewByName(name, index) else: for n in name: self._sheets.insertNewByName(n, index) name = n return LOCalcSheet(self._sheets[name], self) def move(self, name, pos=-1): return self.sheets.move(name, pos) def remove(self, name): return self.sheets.remove(name) def copy(self, source='', target='', pos=-1): index = pos if pos < 0: index = self._sheets.Count + pos + 1 names = source if not names: names = self.names elif isinstance(source, str): names = (source,) new_names = target if not target: new_names = [n + '_2' for n in names] elif isinstance(target, str): new_names = (target,) for i, ns in enumerate(names): self.sheets.copy(ns, new_names[i], index + i) return LOCalcSheet(self._sheets[index], self) def copy_from(self, doc, source='', target='', pos=-1): index = pos if pos < 0: index = self._sheets.Count + pos + 1 names = source if not names: names = doc.names elif isinstance(source, str): names = (source,) new_names = target if not target: new_names = names elif isinstance(target, str): new_names = (target,) for i, n in enumerate(names): self._sheets.importSheet(doc.obj, n, index + i) self.sheets[index + i].name = new_names[i] # ~ doc.getCurrentController().setActiveSheet(sheet) # ~ For controls in sheet # ~ doc.getCurrentController().setFormDesignMode(False) return LOCalcSheet(self._sheets[index], self) def sort(self, reverse=False): names = sorted(self.names, reverse=reverse) for i, n in enumerate(names): self.sheets.move(n, i) return def get_cell(self, index=None): """ index is str 'A1' index is tuple (row, col) """ if index is None: cell = self.selection.first else: cell = LOCellRange(self.active[index].obj, self) return cell def select(self, rango): r = rango if hasattr(rango, 'obj'): r = rango.obj elif isinstance(rango, str): r = self.get_cell(rango).obj self._cc.select(r) return def create_cell_style(self, name=''): obj = self.create_instance('com.sun.star.style.CellStyle') if name: self.cell_style[name] = obj return LOCellStyle(obj) def clear_undo(self): self.obj.getUndoManager().clear() return def filter_by_color(self, cell=None): if cell is None: cell = self.selection.first cr = cell.current_region col = cell.column - cr.column rangos = cell.get_column(col).visible for r in rangos: for row in range(r.rows): c = r[row, 0] if c.back_color != cell.back_color: c.rows_visible = False return def _set_cell(self, k='', v=None, cell=None, value=False): if k: self._sd.setSearchString(k) ranges = self._search.findAll(self._sd) if ranges: ranges = ranges.getRangeAddressesAsString().split(';') for r in ranges: for c in r.split(','): cell = self._sheet.getCellRangeByName(c) if v is None: return cell if cell.getImplementationName() == 'ScCellObj': pattern = re.compile(k, re.IGNORECASE) nv = pattern.sub(v, cell.getString()) if value: cell.setValue(nv) else: cell.setString(nv) return cell if cell: if cell.getImplementationName() == 'ScCellObj': ca = cell.getCellAddress() new_cell = self._sheet.getCellByPosition(ca.Column, ca.Row + 1) if value: new_cell.setValue(v) else: new_cell.setString(v) return new_cell def render(self, data, sheet=0): self.set_search_in(sheet) for k, v in data.items(): self._render_cells(k, v) return class LOCalcSheets(object): def __init__(self, obj, doc): self._obj = obj self._doc = doc def __getitem__(self, index): return LOCalcSheet(self.obj[index], self.doc) @property def obj(self): return self._obj @property def doc(self): return self._doc @property def count(self): return self.obj.Count @property def names(self): return self.obj.ElementNames def copy(self, name, new_name, pos): self.obj.copyByName(name, new_name, pos) return def move(self, name, pos): index = pos if pos < 0: index = self.count + pos + 1 sheet = self.obj[name] self.obj.moveByName(sheet.Name, index) return def remove(self, name): sheet = self.obj[name] self.obj.removeByName(sheet.Name) return class LOCalcSheet(object): def __init__(self, obj, doc): self._obj = obj self._doc = doc self._init_values() def __getitem__(self, index): return LOCellRange(self.obj[index], self.doc) def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): pass def _init_values(self): self._events = None self._dp = self.obj.getDrawPage() self._images = {i.Name: LOImage(i) for i in self._dp} @property def obj(self): return self._obj @property def doc(self): return self._doc @property def images(self): return self._images @property def name(self): return self._obj.Name @name.setter def name(self, value): self._obj.Name = value @property def code_name(self): return self._obj.CodeName @code_name.setter def code_name(self, value): self._obj.CodeName = value @property def color(self): return self._obj.TabColor @color.setter def color(self, value): self._obj.TabColor = get_color(value) @property def active(self): return self.doc.selection.first def activate(self): self.doc.activate(self.obj) return @property def visible(self): return self.obj.IsVisible @visible.setter def visible(self, value): self.obj.IsVisible = value @property def is_protected(self): return self._obj.isProtected() @property def password(self): return '' @visible.setter def password(self, value): self.obj.protect(value) def unprotect(self, value): try: self.obj.unprotect(value) return True except: pass return False def get_cursor(self, cell): return self.obj.createCursorByRange(cell) def exists_chart(self, name): return name in self.obj.Charts.ElementNames @property def forms(self): return LOForms(self._dp.getForms(), self.doc) @property def events(self): return self._events @events.setter def events(self, controllers): self._events = controllers self._connect_listeners() def _connect_listeners(self): if self.events is None: return listeners = { 'addModifyListener': EventsModify, } for key, value in listeners.items(): getattr(self.obj, key)(listeners[key](self.events)) print('add_listener') return def get_range_by_address(self, address): row_s = address.StartRow row_e = address.EndRow + 1 col_s = address.StartColumn col_e = address.EndColumn + 1 return LOCellRange(self.obj[row_s:row_e,col_s:col_e], self.doc) def render(self, data, rango=None, clean=False): if rango is None: ra = self.obj.getPrintAreas()[0] rango = self.get_range_by_address(ra) rango.render(data, clean) return rango def find(self, search_string, rango=None): if rango is None: ra = self.obj.getPrintAreas()[0] rango = self.get_range_by_address(ra) cell = rango.find(search_string) return cell class LOWriter(LODocument): def __init__(self, obj): super().__init__(obj) @property def obj(self): return self._obj @property def string(self): return self._obj.getText().String @property def text(self): return self._obj.getText() @property def cursor(self): return self.text.createTextCursor() @property def paragraphs(self): return [LOTextRange(p) for p in self.text] @property def selection(self): sel = self.obj.getCurrentSelection() 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() if data.startswith('\n'): c = data.split('\n') for i in range(len(c)-1): self.text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False) else: self.text.insertString(cursor, data, False) return def insert_table(self, data, cursor=None): cursor = cursor or self.selection.cursor.getEnd() table = self.obj.createInstance('com.sun.star.text.TextTable') rows = len(data) cols = len(data[0]) table.initialize(rows, cols) self.insert_content(cursor, table) table.DataArray = data return WriterTable(table) def create_chart(self, tipo, cursor=None): cursor = cursor or self.selection.cursor.getEnd() chart = LOChart(None, tipo) chart.cursor = cursor chart.doc = self return chart def insert_content(self, cursor, data, replace=False): self.text.insertTextContent(cursor, data, replace) return # ~ f = doc.createInstance('com.sun.star.text.TextFrame') # ~ f.setSize(Size(10000, 500)) def insert_image(self, path, **kwargs): cursor = kwargs.get('cursor', self.selection.cursor.getEnd()) w = kwargs.get('width', 1000) h = kwargs.get('Height', 1000) image = self.create_instance('com.sun.star.text.GraphicObject') image.GraphicURL = _path_url(path) image.AnchorType = AS_CHARACTER image.Width = w image.Height = h self.insert_content(cursor, image) return def go_start(self): cursor = self._cc.getViewCursor() cursor.gotoStart(False) return cursor def go_end(self): cursor = self._cc.getViewCursor() cursor.gotoEnd(False) return cursor def select(self, text): 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): def __init__(self, obj): self._obj = obj self._is_paragraph = self.obj.ImplementationName == 'SwXParagraph' self._is_table = self.obj.ImplementationName == 'SwXTextTable' @property def obj(self): return self._obj @property def is_paragraph(self): return self._is_paragraph @property def is_table(self): return self._is_table @property def string(self): return self.obj.String @property def text(self): return self.obj.getText() @property def cursor(self): return self.text.createTextCursorByRange(self.obj) class LOBase(object): TYPES = { str: 'setString', int: 'setInt', float: 'setFloat', bool: 'setBoolean', Date: 'setDate', Time: 'setTime', DateTime: 'setTimestamp', } # ~ setArray # ~ setBinaryStream # ~ setBlob # ~ setByte # ~ setBytes # ~ setCharacterStream # ~ setClob # ~ setNull # ~ setObject # ~ setObjectNull # ~ setObjectWithInfo # ~ setPropertyValue # ~ setRef def __init__(self, name, path='', **kwargs): self._name = name self._path = path self._dbc = create_instance('com.sun.star.sdb.DatabaseContext') if path: path_url = _path_url(path) db = self._dbc.createInstance() db.URL = 'sdbc:embedded:firebird' db.DatabaseDocument.storeAsURL(path_url, ()) if not self.exists: self._dbc.registerDatabaseLocation(name, path_url) else: if name.startswith('odbc:'): self._con = self._odbc(name, kwargs) else: db = self._dbc.getByName(name) self.path = _path_system(self._dbc.getDatabaseLocation(name)) self._con = db.getConnection('', '') if self._con is None: msg = 'Not connected to: {}'.format(name) else: msg = 'Connected to: {}'.format(name) debug(msg) def _odbc(self, name, kwargs): dm = create_instance('com.sun.star.sdbc.DriverManager') args = dict_to_property(kwargs) try: con = dm.getConnectionWithInfo('sdbc:{}'.format(name), args) return con except Exception as e: error(str(e)) return None @property def obj(self): return self._obj @property def name(self): return self._name @property def connection(self): return self._con @property def path(self): return self._path @path.setter def path(self, value): self._path = value @property def exists(self): return self._dbc.hasRegisteredDatabase(self.name) @classmethod def register(self, path, name): if not self._dbc.hasRegisteredDatabase(name): self._dbc.registerDatabaseLocation(name, _path_url(path)) return def revoke(self, name): self._dbc.revokeDatabaseLocation(name) return True def save(self): # ~ self._db.connection.commit() # ~ self._db.connection.getTables().refresh() # ~ oDisp.executeDispatch(oFrame,".uno:DBRefreshTables", "", 0, Array()) self._obj.DatabaseDocument.store() self.refresh() return def close(self): self._con.close() return def refresh(self): self._con.getTables().refresh() return def get_tables(self): tables = self._con.getTables() tables = [tables.getByIndex(i) for i in range(tables.Count)] return tables def cursor(self, sql, params): cursor = self._con.prepareStatement(sql) for i, v in enumerate(params, 1): if not type(v) in self.TYPES: error('Type not support') debug((i, type(v), v, self.TYPES[type(v)])) getattr(cursor, self.TYPES[type(v)])(i, v) return cursor def execute(self, sql, params): debug(sql) if params: cursor = self.cursor(sql, params) cursor.execute() else: cursor = self._con.createStatement() cursor.execute(sql) # ~ resulset = cursor.executeQuery(sql) # ~ rows = cursor.executeUpdate(sql) self.save() return cursor class LODrawImpress(LODocument): def __init__(self, obj): super().__init__(obj) @property def draw_page(self): return self._cc.getCurrentPage() def insert_image(self, path, **kwargs): w = kwargs.get('width', 3000) h = kwargs.get('Height', 3000) x = kwargs.get('X', 1000) y = kwargs.get('Y', 1000) image = self.create_instance('com.sun.star.drawing.GraphicObjectShape') image.GraphicURL = _path_url(path) image.Size = Size(w, h) image.Position = Point(x, y) self.draw_page.add(image) return class LOImpress(LODrawImpress): def __init__(self, obj): super().__init__(obj) class LODraw(LODrawImpress): def __init__(self, obj): super().__init__(obj) @property def selection(self): sel = self.obj.getCurrentSelection() return sel class LOMath(LODocument): def __init__(self, obj): super().__init__(obj) class LOBasicIde(LODocument): def __init__(self, obj): super().__init__(obj) @property def selection(self): sel = self._cc.getSelection() return sel class LOCellRange(object): def __init__(self, obj, doc): self._obj = obj self._doc = doc self._init_values() def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): pass 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._sd = None self._type_obj = self.obj.ImplementationName self._type_content = EMPTY if self._type_obj == OBJ_CELL: self._type_content = self.obj.getType() return @property def obj(self): return self._obj @property def doc(self): return self._doc @property def type(self): return self._type_obj @property def type_content(self): return self._type_content @property def first(self): if self.type == OBJ_RANGES: obj = LOCellRange(self.obj[0][0,0], self.doc) else: obj = LOCellRange(self.obj[0,0], self.doc) return obj @property def value(self): v = None if self._type_content == VALUE: v = self.obj.getValue() elif self._type_content == TEXT: v = self.obj.getString() elif self._type_content == FORMULA: v = self.obj.getFormula() return v @value.setter def value(self, data): if isinstance(data, str): if data.startswith('='): self.obj.setFormula(data) else: self.obj.setString(data) elif isinstance(data, (int, float, bool)): self.obj.setValue(data) elif isinstance(data, datetime.datetime): d = data.toordinal() t = (data - datetime.datetime.fromordinal(d)).seconds / SECONDS_DAY self.obj.setValue(d - DATE_OFFSET + t) elif isinstance(data, datetime.date): d = data.toordinal() self.obj.setValue(d - DATE_OFFSET) elif isinstance(data, datetime.time): d = (data.hour * 3600 + data.minute * 60 + data.second) / SECONDS_DAY self.obj.setValue(d) @property def data(self): return self.obj.getDataArray() @data.setter def data(self, values): self.obj.setDataArray(values) @property def formula(self): return self.obj.getFormulaArray() @formula.setter def formula(self, values): self.obj.setFormulaArray(values) @property def column(self): a = self.address if hasattr(a, 'Column'): c = a.Column else: c = a.StartColumn return c @property def columns(self): return self._obj.Columns.Count @property def row(self): a = self.address if hasattr(a, 'Row'): r = a.Row else: r = a.StartRow return r @property def rows(self): return self._obj.Rows.Count def to_size(self, rows, cols): cursor = self.sheet.get_cursor(self.obj[0,0]) cursor.collapseToSize(cols, rows) return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc) def copy_from(self, rango, formula=False): data = rango if isinstance(rango, LOCellRange): if formula: data = rango.formula else: data = rango.data rows = len(data) cols = len(data[0]) 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): rango = cell.to_size(self.rows, self.columns) if formula: rango.formula = self.data else: rango.data = self.data return def copy(self, source): self.sheet.obj.copyRange(self.address, source.range_address) return def transpose(self, formula=False): data = self.data if formula: data = self.formula data = tuple(zip(*data)) self.clear(1023) self[0,0].copy_from(data, formula=formula) return def transpose2(self): # ~ 'Flags': 'A', # ~ 'FormulaCommand': 0, # ~ 'SkipEmptyCells': False, # ~ 'AsLink': False, # ~ 'MoveMode': 4, args = { 'Transpose': True, } args = dict_to_property(args) self.select() copy() self.clear(1023) self[0,0].select() call_dispatch(self._doc, '.uno:InsertContents', args) set_clipboard('') return def offset(self, row=1, col=0): ra = self.obj.getRangeAddress() col = ra.EndColumn + col row = ra.EndRow + row return LOCellRange(self.sheet[row, col].obj, self.doc) @property def next_cell(self): a = self.current_region.address if hasattr(a, 'StartColumn'): col = a.StartColumn else: col = a.Column if hasattr(a, 'EndRow'): row = a.EndRow + 1 else: row = a.Row + 1 return LOCellRange(self.sheet[row, col].obj, self.doc) @property def sheet(self): return LOCalcSheet(self.obj.Spreadsheet, self.doc) @property def charts(self): return self.obj.Spreadsheet.Charts @property def ps(self): ps = Rectangle() s = self.obj.Size p = self.obj.Position ps.X = p.X ps.Y = p.Y ps.Width = s.Width ps.Height = s.Height return ps @property def draw_page(self): return self.sheet.obj.getDrawPage() @property def name(self): return self.obj.AbsoluteName @property def address(self): if self._type_obj == OBJ_CELL: a = self.obj.getCellAddress() elif self._type_obj == OBJ_RANGE: a = self.obj.getRangeAddress() else: 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]) cursor.collapseToCurrentRegion() return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc) @property def merged_area(self): cursor = self.sheet.get_cursor(self.obj[0,0]) cursor.collapseToMergedArea() return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc) @property def visible(self): cursor = self.sheet.get_cursor(self.obj) rangos = [LOCellRange(self.sheet[r.AbsoluteName].obj, self.doc) for r in cursor.queryVisibleCells()] return tuple(rangos) @property def empty(self): cursor = self.sheet.get_cursor(self.obj) rangos = [LOCellRange(self.sheet[r.AbsoluteName].obj, self.doc) for r in cursor.queryEmptyCells()] return tuple(rangos) @property def back_color(self): return self._obj.CellBackColor @back_color.setter def back_color(self, value): self._obj.CellBackColor = get_color(value) @property def cell_style(self): return self.obj.CellStyle @cell_style.setter def cell_style(self, value): self.obj.CellStyle = value @property def auto_format(self): return self.obj.CellStyle @auto_format.setter def auto_format(self, value): self.obj.autoFormat(value) def auto_width(self): self.obj.Columns.OptimalWidth = True return def insert_image(self, path, **kwargs): s = self.obj.Size w = kwargs.get('Width', s.Width) h = kwargs.get('Height', s.Height) data = kwargs.get('Data', '') img = self.doc.create_instance('com.sun.star.drawing.GraphicObjectShape') img.GraphicURL = _path_url(path) # ~ img.ResizeWithCell = True self.draw_page.add(img) img.setSize(Size(w, h)) img.Anchor = self.obj return def insert_shape(self, tipo, **kwargs): s = self.obj.Size w = kwargs.get('width', s.Width) h = kwargs.get('Height', s.Height) img = self.doc.create_instance('com.sun.star.drawing.{}Shape'.format(tipo)) set_properties(img, kwargs) self.draw_page.add(img) img.Anchor = self.obj img.setSize(Size(w, h)) return def select(self): self.doc._cc.select(self.obj) return def in_range(self, rango): if isinstance(rango, LOCellRange): address = rango.address else: address = rango.getRangeAddress() cursor = self.sheet.get_cursor(self.obj) result = cursor.queryIntersection(address) return bool(result.Count) def fill(self, source=1): self.obj.fillAuto(0, source) return def clear(self, what=31): # ~ http://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1sheet_1_1CellFlags.html self.obj.clearContents(what) return @property def rows_visible(self): return self._obj.getRows().IsVisible @rows_visible.setter def rows_visible(self, value): self._obj.getRows().IsVisible = value @property def columns_visible(self): return self._obj.getColumns().IsVisible @columns_visible.setter def columns_visible(self, value): self._obj.getColumns().IsVisible = value def get_column(self, index=0, first=False): ca = self.address ra = self.current_region.address if hasattr(ca, 'Column'): col = ca.Column else: col = ca.StartColumn + index start = 1 if first: start = 0 if hasattr(ra, 'Row'): row_start = ra.Row + start row_end = ra.Row + 1 else: row_start = ra.StartRow + start row_end = ra.EndRow + 1 return LOCellRange(self.sheet[row_start:row_end, col:col+1].obj, self.doc) def import_csv(self, path, **kwargs): data = import_csv(path, **kwargs) self.copy_from(data) return def export_csv(self, path, **kwargs): data = self.current_region.data export_csv(path, data, **kwargs) return def create_chart(self, tipo): chart = LOChart(None, tipo) 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 @property def validation(self): return self.obj.Validation @validation.setter def validation(self, values): is_list = False current = self.validation for k, v in values.items(): if k == 'Type' and v == 6: is_list = True if k == 'Formula1' and is_list: if isinstance(v, (tuple, list)): v = ';'.join(['"{}"'.format(i) for i in v]) setattr(current, k, v) self.obj.Validation = current def _set_new_value(self, cell, search, value): if not cell.ImplementationName == 'ScCellObj': return if isinstance(value, str): pattern = re.compile(search, re.IGNORECASE) new_value = pattern.sub(value, cell.String) cell.String = new_value else: cell.Value = value return def rows_insert(self, count=0): if not count: count = self.rows self.obj.Rows.insertByIndex(0, count) return def rows_merge(self): for r in range(self.rows): self[r].obj.merge(True) return def copy_format_from(self, rango): rango.select() copy(self._doc) self.select() args = { 'Flags': 'T', 'MoveMode': 4, } args = dict_to_property(args) url = '.uno:InsertContents' call_dispatch(self._doc, url, args) return def _render_list(self, key, values): rango = None total_rows = len(values) try: rango = self.sheet[key] if total_rows > 1: cells = rango[0,0].offset(1).to_size(total_rows - 1, 1) name = cells.name cells.rows_insert() cells = self.sheet[name] cells.copy_format_from(rango) except Exception as e: print(key, e) if rango is None: pass else: headers = list(rango.data[0]) positions = {} for i, v in enumerate(headers): if not v: continue k = v[1:-1] if k in values[0]: positions[k] = i data = [] for row in values: new_row = headers[:] for k, v in positions.items(): new_row[v] = row[k] data.append(new_row) cell = rango[0,0] cell.copy_from(data) return def _render_value(self, key, value, parent=''): if isinstance(value, dict): for k, v in value.items(): self._render_value(k, v, key) return elif isinstance(value, (list, tuple)): self._render_list(key, value) return search = f'{{{key}}}' if parent: search = f'{{{parent}.{key}}}' ranges = self.find_all(search) for cell in ranges or range(0): self._set_new_value(cell, search, value) return def clean_render(self, template='\{(\w.+)\}'): self._sd.SearchRegularExpression = True self._sd.setSearchString(template) self.obj.replaceAll(self._sd) return def find(self, search_string): if self._sd is None: self._sd = self.sheet.obj.createSearchDescriptor() self._sd.SearchCaseSensitive = False self._sd.setSearchString(search_string) cell = self.obj.findFirst(self._sd) return LOCellRange(self.sheet[cell.AbsoluteName].obj, self.doc) def find_all(self, search_string): if self._sd is None: self._sd = self.sheet.obj.createSearchDescriptor() self._sd.SearchCaseSensitive = False self._sd.setSearchString(search_string) ranges = self.obj.findAll(self._sd) return ranges def render(self, data, clean=False): self._sd = self.sheet.obj.createSearchDescriptor() self._sd.SearchCaseSensitive = False for k, v in data.items(): self._render_value(k, v) if clean: self.clean_render() return class EventsListenerBase(unohelper.Base, XEventListener): def __init__(self, controller, name, window=None): self._controller = controller 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: self._window.setMenuBar(None) class EventsButton(EventsListenerBase, XActionListener): def __init__(self, controller, name): super().__init__(controller, name) def actionPerformed(self, event): event_name = '{}_action'.format(self._name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return class EventsMouse(EventsListenerBase, XMouseListener, XMouseMotionListener): def __init__(self, controller, name): super().__init__(controller, name) def mousePressed(self, event): event_name = '{}_click'.format(self._name) if event.ClickCount == 2: event_name = '{}_double_click'.format(self._name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return def mouseReleased(self, event): pass def mouseEntered(self, event): pass def mouseExited(self, event): pass # ~ XMouseMotionListener def mouseMoved(self, event): pass def mouseDragged(self, event): pass class EventsMouseLink(EventsMouse): def mouseEntered(self, event): obj = event.Source.Model obj.TextColor = get_color('blue') return def mouseExited(self, event): obj = event.Source.Model obj.TextColor = 0 return class EventsMouseGrid(EventsMouse): selected = False def mousePressed(self, event): super().mousePressed(event) # ~ obj = event.Source # ~ col = obj.getColumnAtPoint(event.X, event.Y) # ~ row = obj.getRowAtPoint(event.X, event.Y) # ~ print(col, row) # ~ if col == -1 and row == -1: # ~ if self.selected: # ~ obj.deselectAllRows() # ~ else: # ~ obj.selectAllRows() # ~ self.selected = not self.selected return def mouseReleased(self, event): # ~ obj = event.Source # ~ col = obj.getColumnAtPoint(event.X, event.Y) # ~ row = obj.getRowAtPoint(event.X, event.Y) # ~ if row == -1 and col > -1: # ~ gdm = obj.Model.GridDataModel # ~ for i in range(gdm.RowCount): # ~ gdm.updateRowHeading(i, i + 1) return class EventsModify(EventsListenerBase, XModifyListener): def __init__(self, controller): super().__init__(controller) def modified(self, event): event_name = '{}_modified'.format(event.Source.Name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return class EventsItem(EventsListenerBase, XItemListener): def __init__(self, controller, name): super().__init__(controller, name) def disposing(self, event): pass def itemStateChanged(self, event): event_name = '{}_item_changed'.format(self.name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return class EventsItemRoadmap(EventsItem): def itemStateChanged(self, event): dialog = event.Source.Context.Model dialog.Step = event.ItemId + 1 return class EventsFocus(EventsListenerBase, XFocusListener): def __init__(self, controller, name): super().__init__(controller, name) def focusGained(self, event): service = event.Source.Model.ImplementationName if service == 'stardiv.Toolkit.UnoControlListBoxModel': return obj = event.Source.Model obj.BackgroundColor = COLOR_ON_FOCUS def focusLost(self, event): obj = event.Source.Model obj.BackgroundColor = -1 class EventsKey(EventsListenerBase, XKeyListener): """ event.KeyChar event.KeyCode event.KeyFunc event.Modifiers """ def __init__(self, controller, name): super().__init__(controller, name) def keyPressed(self, event): pass def keyReleased(self, event): event_name = '{}_key_released'.format(self._name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) 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 event.KeyCode event.KeyFunc event.Modifiers """ def __init__(self, cls): super().__init__(cls.events, cls.name) self._cls = cls def keyPressed(self, event): pass def keyReleased(self, event): event_name = '{}_key_released'.format(self._cls.name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) else: if event.KeyFunc == QUIT and hasattr(self._cls, 'close'): self._cls.close() return class EventsWindow(EventsListenerBase, XTopWindowListener, XWindowListener): def __init__(self, cls): self._cls = cls super().__init__(cls.events, cls.name, cls._window) def windowOpened(self, event): event_name = '{}_opened'.format(self._name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return def windowActivated(self, event): control_name = '{}_activated'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) return def windowDeactivated(self, event): control_name = '{}_deactivated'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) return def windowMinimized(self, event): pass def windowNormalized(self, event): pass def windowClosing(self, event): if self._window: control_name = 'window_closing' else: control_name = '{}_closing'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) # ~ else: # ~ if not self._modal and not self._block: # ~ event.Source.Visible = False return def windowClosed(self, event): control_name = '{}_closed'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) return # ~ XWindowListener def windowResized(self, event): 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) return def windowMoved(self, event): pass def windowShown(self, event): pass def windowHidden(self, event): pass class EventsMenu(EventsListenerBase, XMenuListener): def __init__(self, controller): super().__init__(controller, '') def itemHighlighted(self, event): pass def itemSelected(self, event): name = event.Source.getCommand(event.MenuId) if name.startswith('menu'): event_name = '{}_selected'.format(name) else: event_name = 'menu_{}_selected'.format(name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return def itemActivated(self, event): return def itemDeactivated(self, event): return class UnoBaseObject(object): def __init__(self, obj): self._obj = obj self._model = self.obj.Model self._rules = {} @property def obj(self): return self._obj @property def model(self): return self._model @property def name(self): return self.model.Name @property def parent(self): ps = self.obj.getContext().PosSize return self.obj.getContext() def _get_possize(self, name): ps = self.obj.getPosSize() return getattr(ps, name) def _set_possize(self, name, value): ps = self.obj.getPosSize() setattr(ps, name, value) self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, POSSIZE) return @property def x(self): if hasattr(self.model, 'PositionX'): return self.model.PositionX return self._get_possize('X') @x.setter def x(self, value): if hasattr(self.model, 'PositionX'): self.model.PositionX = value else: self._set_possize('X', value) @property def y(self): if hasattr(self.model, 'PositionY'): return self.model.PositionY return self._get_possize('Y') @y.setter def y(self, value): if hasattr(self.model, 'PositionY'): self.model.PositionY = value else: self._set_possize('Y', value) @property def width(self): return self._model.Width @width.setter def width(self, value): self.model.Width = value @property def ps_width(self): return self._get_possize('Width') @ps_width.setter def ps_width(self, value): self._set_possize('Width', value) @property def height(self): return self.model.Height @height.setter def height(self, value): self.model.Height = value @property def ps_height(self): return self._get_possize('Height') @ps_height.setter def ps_height(self, value): self._set_possize('Height', value) @property def size(self): ps = self.obj.getPosSize() return (ps.Width, ps.Height) @size.setter def size(self, value): ps = self.obj.getPosSize() ps.Width = value[0] ps.Height = value[1] self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, SIZE) @property def tag(self): return self.model.Tag @tag.setter def tag(self, value): self.model.Tag = value @property def visible(self): return self.obj.Visible @visible.setter def visible(self, value): self.obj.setVisible(value) @property def enabled(self): return self.model.Enabled @enabled.setter def enabled(self, value): self.model.Enabled = value @property def step(self): return self.model.Step @step.setter def step(self, value): self.model.Step = value @property def back_color(self): return self.model.BackgroundColor @back_color.setter def back_color(self, value): self.model.BackgroundColor = value @property def rules(self): return self._rules @rules.setter def rules(self, value): self._rules = value def set_focus(self): self.obj.setFocus() return def center(self, horizontal=True, vertical=False): p = self.parent.Model w = p.Width h = p.Height if horizontal: x = w / 2 - self.width / 2 self.x = x if vertical: y = h / 2 - self.height / 2 self.y = y return 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): self.x = origin.x self.y = origin.y self.width = origin.width self.height = origin.height return class UnoLabel(UnoBaseObject): def __init__(self, obj): super().__init__(obj) @property def type(self): return 'label' @property def value(self): return self.model.Label @value.setter def value(self, value): self.model.Label = value class UnoLabelLink(UnoLabel): def __init__(self, obj): super().__init__(obj) @property def type(self): return 'link' class UnoButton(UnoBaseObject): def __init__(self, obj): super().__init__(obj) @property def type(self): return 'button' @property def value(self): return self.model.Label @value.setter def value(self, value): self.model.Label = value class UnoText(UnoBaseObject): def __init__(self, obj): super().__init__(obj) @property def type(self): return 'text' @property def value(self): return self.model.Text @value.setter def value(self, value): self.model.Text = value def validate(self): return class UnoListBox(UnoBaseObject): def __init__(self, obj): super().__init__(obj) @property def type(self): return 'listbox' @property def value(self): return self.obj.getSelectedItem() @property def count(self): return len(self.data) @property def data(self): return self.model.StringItemList @data.setter def data(self, values): 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) else: self.obj.selectItemPos(pos, True) return def clear(self): self.model.removeAllItems() return def _set_image_url(self, image): 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) def insert(self, value, path='', pos=-1, show=True): if pos < 0: pos = self.count if path: self.model.insertItem(pos, value, self._set_image_url(path)) else: self.model.insertItemText(pos, value) if show: self.select(pos) return class UnoGrid(UnoBaseObject): def __init__(self, obj): super().__init__(obj) self._gdm = self._model.GridDataModel # ~ self._data = [] self._columns = {} # ~ self._format_columns = () def __getitem__(self, index): value = self._gdm.getCellData(index[0], index[1]) return value @property def type(self): return 'grid' def _format_cols(self): rows = tuple(tuple( self._format_columns[i].format(r) for i, r in enumerate(row)) for row in self._data ) return rows # ~ @property # ~ def format_columns(self): # ~ return self._format_columns # ~ @format_columns.setter # ~ 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.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) return @property def row(self): return self.obj.CurrentRow @property def rows(self): return self._gdm.RowCount @property def column(self): return self.obj.CurrentColumn @property def columns(self): return self._gdm.ColumnCount def set_cell_tooltip(self, col, row, value): self._gdm.updateCellToolTip(col, row, value) return def get_cell_tooltip(self, col, row): value = self._gdm.getCellToolTip(col, row) return value def _validate_column(self, data): row = [] for i, d in enumerate(data): if i in self._columns: if 'image' in self._columns[i]: row.append(self._columns[i]['image']) else: 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) self._gdm.addRow(self.rows + 1, data) return def remove_row(self, row): self._gdm.removeRow(row) # ~ del self._data[row] self.update_row_heading() return 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.update_row_heading() return def set_column_image(self, column, path): gp = create_instance('com.sun.star.graphic.GraphicProvider') data = dict_to_property({'URL': _path_url(path)}) image = gp.queryGraphic(data) if not column in self._columns: self._columns[column] = {} self._columns[column]['image'] = image return class UnoRoadmap(UnoBaseObject): def __init__(self, obj): super().__init__(obj) self._options = () @property def options(self): return self._options @options.setter def options(self, values): self._options = values for i, v in enumerate(values): opt = self.model.createInstance() opt.ID = i opt.Label = v self.model.insertByIndex(i, opt) return @property def enabled(self): return True @enabled.setter def enabled(self, value): for m in self.model: m.Enabled = value return def set_enabled(self, index, value): self.model.getByIndex(index).Enabled = value 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, 'button': UnoButton, 'text': UnoText, 'listbox': UnoListBox, 'grid': UnoGrid, 'link': UnoLabelLink, 'roadmap': UnoRoadmap, 'tree': UnoTree, 'tab': UnoTab, # ~ 'image': UnoImage, # ~ 'radio': UnoRadio, # ~ 'groupbox': UnoGroupBox, '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] def add_listeners(events, control, name=''): listeners = { 'addActionListener': EventsButton, 'addMouseListener': EventsMouse, 'addItemListener': EventsItem, 'addFocusListener': EventsFocus, 'addKeyListener': EventsKey, 'addTabListener': EventsTab, } if hasattr(control, 'obj'): control = contro.obj # ~ debug(control.ImplementationName) is_grid = control.ImplementationName == 'stardiv.Toolkit.GridControl' is_link = control.ImplementationName == 'stardiv.Toolkit.UnoFixedHyperlinkControl' is_roadmap = control.ImplementationName == 'stardiv.Toolkit.UnoRoadmapControl' for key, value in listeners.items(): if hasattr(control, key): if is_grid and key == 'addMouseListener': control.addMouseListener(EventsMouseGrid(events, name)) continue if is_link and key == 'addMouseListener': control.addMouseListener(EventsMouseLink(events, name)) continue if is_roadmap and key == 'addItemListener': control.addItemListener(EventsItemRoadmap(events, 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 class WriterTable(ObjectBase): def __init__(self, obj): super().__init__(obj) def __getitem__(self, key): obj = super().__getitem__(key) return WriterTableRange(obj, key, self.name) @property def name(self): return self.obj.Name @name.setter def name(self, value): self.obj.Name = value class WriterTableRange(ObjectBase): def __init__(self, obj, index, table_name): self._index = index self._table_name = table_name super().__init__(obj) self._is_cell = hasattr(self.obj, 'CellName') def __getitem__(self, key): obj = super().__getitem__(key) return WriterTableRange(obj, key, self._table_name) @property def value(self): return self.obj.String @value.setter def value(self, value): self.obj.String = value @property def data(self): return self.obj.getDataArray() @data.setter def data(self, values): if isinstance(values, list): values = tuple(values) self.obj.setDataArray(values) @property def rows(self): return len(self.data) @property def columns(self): return len(self.data[0]) @property def name(self): if self._is_cell: name = '{}.{}'.format(self._table_name, self.obj.CellName) elif isinstance(self._index, str): name = '{}.{}'.format(self._table_name, self._index) else: c1 = self.obj[0,0].CellName c2 = self.obj[self.rows-1,self.columns-1].CellName name = '{}.{}:{}'.format(self._table_name, c1, c2) return name def get_cell(self, *index): return self[index] def get_column(self, index=0, start=1): return self[start:self.rows,index:index+1] def get_series(self): class Serie(): pass series = [] for i in range(self.columns): serie = Serie() serie.label = self.get_cell(0,i).name serie.data = self.get_column(i).data serie.values = self.get_column(i).name series.append(serie) return series class ChartFormat(object): def __call__(self, obj): for k, v in self.__dict__.items(): if hasattr(obj, k): setattr(obj, k, v) class LOChart(object): BASE = 'com.sun.star.chart.{}Diagram' def __init__(self, obj, tipo=''): self._obj = obj self._type = tipo self._name = '' self._table = None self._data = () self._data_series = () self._cell = None self._cursor = None self._doc = None self._title = ChartFormat() self._subtitle = ChartFormat() self._legend = ChartFormat() self._xaxistitle = ChartFormat() self._yaxistitle = ChartFormat() self._xaxis = ChartFormat() self._yaxis = ChartFormat() self._xmaingrid = ChartFormat() self._ymaingrid = ChartFormat() self._xhelpgrid = ChartFormat() self._yhelpgrid = ChartFormat() self._area = ChartFormat() self._wall = ChartFormat() self._dim3d = False self._series = () self._labels = () return def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.insert() @property def obj(self): return self._obj @obj.setter def obj(self, value): self._obj = value @property def name(self): return self._name @name.setter def name(self, value): self._name = value @property def type(self): return self._type @type.setter def type(self, value): self._type = value @property def table(self): return self._table @table.setter def table(self, value): self._table = value @property def data(self): return self._data @data.setter def data(self, value): self._data = value @property def cell(self): return self._cell @cell.setter def cell(self, value): self._cell = value self.doc = value.doc @property def cursor(self): return self._cursor @cursor.setter def cursor(self, value): self._cursor = value @property def doc(self): return self._doc @doc.setter def doc(self, value): self._doc = value @property def width(self): return self._width @width.setter def width(self, value): self._width = value @property def height(self): return self._height @height.setter def height(self, value): self._height = value @property def title(self): return self._title @property def subtitle(self): return self._subtitle @property def legend(self): return self._legend @property def xaxistitle(self): return self._xaxistitle @property def yaxistitle(self): return self._yaxistitle @property def xaxis(self): return self._xaxis @property def yaxis(self): return self._yaxis @property def xmaingrid(self): return self._xmaingrid @property def ymaingrid(self): return self._ymaingrid @property def xhelpgrid(self): return self._xhelpgrid @property def yhelpgrid(self): return self._yhelpgrid @property def area(self): return self._area @property def wall(self): return self._wall @property def dim3d(self): return self._dim3d @dim3d.setter def dim3d(self, value): self._dim3d = value @property def series(self): return self._series @series.setter def series(self, value): self._series = value @property def data_series(self): return self._series @data_series.setter def data_series(self, value): self._data_series = value @property def labels(self): return self._labels @labels.setter def labels(self, value): self._labels = value def _add_series_writer(self, chart): dp = self.doc.create_instance('com.sun.star.chart2.data.DataProvider') chart.attachDataProvider(dp) chart_type = chart.getFirstDiagram().getCoordinateSystems()[0].getChartTypes()[0] self._data_series = self.table[self.data].get_series() series = [self._create_serie(dp, s) for s in self._data_series[1:]] chart_type.setDataSeries(tuple(series)) chart_data = chart.getData() chart_data.ComplexRowDescriptions = self._data_series[0].data return def _get_series(self): rango = self._data_series class Serie(): pass series = [] for i in range(0, rango.columns, 2): serie = Serie() serie.label = rango[0, i+1].name serie.xvalues = rango.get_column(i).name serie.values = rango.get_column(i+1).name series.append(serie) return series def _add_series_calc(self, chart): dp = self.doc.create_instance('com.sun.star.chart2.data.DataProvider') chart.attachDataProvider(dp) chart_type = chart.getFirstDiagram().getCoordinateSystems()[0].getChartTypes()[0] series = self._get_series() series = [self._create_serie(dp, s) for s in series] chart_type.setDataSeries(tuple(series)) return def _create_serie(self, dp, data): serie = create_instance('com.sun.star.chart2.DataSeries') rango = data.values is_x = hasattr(data, 'xvalues') if is_x: xrango = data.xvalues rango_label = data.label lds = create_instance('com.sun.star.chart2.data.LabeledDataSequence') values = self._create_data(dp, rango, 'values-y') lds.setValues(values) if data.label: label = self._create_data(dp, rango_label, '') lds.setLabel(label) xlds = () if is_x: xlds = create_instance('com.sun.star.chart2.data.LabeledDataSequence') values = self._create_data(dp, xrango, 'values-x') xlds.setValues(values) if is_x: serie.setData((lds, xlds)) else: serie.setData((lds,)) return serie def _create_data(self, dp, rango, role): data = dp.createDataSequenceByRangeRepresentation(rango) if not data is None: data.Role = role return data def _from_calc(self): ps = self.cell.ps ps.Width = self.width ps.Height = self.height charts = self.cell.charts data = () if self.data: data = (self.data.address,) charts.addNewByName(self.name, ps, data, True, True) self.obj = charts.getByName(self.name) chart = self.obj.getEmbeddedObject() chart.setDiagram(chart.createInstance(self.BASE.format(self.type))) if not self.data: self._add_series_calc(chart) return chart def _from_writer(self): obj = self.doc.create_instance('com.sun.star.text.TextEmbeddedObject') obj.setPropertyValue('CLSID', '12DCAE26-281F-416F-a234-c3086127382e') obj.Name = self.name obj.setSize(Size(self.width, self.height)) self.doc.insert_content(self.cursor, obj) self.obj = obj chart = obj.getEmbeddedObject() tipo = self.type if self.type == 'Column': tipo = 'Bar' chart.Diagram.Vertical = True chart.setDiagram(chart.createInstance(self.BASE.format(tipo))) chart.DataSourceLabelsInFirstColumn = True if isinstance(self.data, str): self._add_series_writer(chart) else: chart_data = chart.getData() labels = [r[0] for r in self.data] data = [(r[1],) for r in self.data] 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'))) return chart def insert(self): if not self.cell is None: chart = self._from_calc() elif not self.cursor is None: chart = self._from_writer() diagram = chart.Diagram if self.type == 'Bar': diagram.Vertical = True if hasattr(self.title, 'String'): chart.HasMainTitle = True self.title(chart.Title) if hasattr(self.subtitle, 'String'): chart.HasSubTitle = True self.subtitle(chart.SubTitle) if self.legend.__dict__: chart.HasLegend = True self.legend(chart.Legend) if self.xaxistitle.__dict__: diagram.HasXAxisTitle = True self.xaxistitle(diagram.XAxisTitle) if self.yaxistitle.__dict__: diagram.HasYAxisTitle = True self.yaxistitle(diagram.YAxisTitle) if self.dim3d: diagram.Dim3D = True if self.series: data_series = chart.getFirstDiagram( ).getCoordinateSystems( )[0].getChartTypes()[0].DataSeries for i, serie in enumerate(data_series): for k, v in self.series[i].items(): if hasattr(serie, k): setattr(serie, k, v) 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): self._obj = self._create(properties) self._init_values() def _init_values(self): self._model = self._obj.Model self._init_controls() self._events = None self._color_on_focus = -1 self._id_extension = '' self._images = 'images' return def _create(self, properties): path = properties.pop('Path', '') if path: dp = create_instance('com.sun.star.awt.DialogProvider', True) return dp.createDialog(_path_url(path)) if 'Location' in properties: location = properties.get('Location', 'application') library = properties.get('Library', 'Standard') if location == 'user': location = 'application' dp = create_instance('com.sun.star.awt.DialogProvider', True) path = 'vnd.sun.star.script:{}.{}?location={}'.format( library, properties['Name'], location) if location == 'document': uid = get_document().uid path = 'vnd.sun.star.tdoc:/{}/Dialogs/{}/{}.xml'.format( uid, library, properties['Name']) return dp.createDialog(path) dlg = create_instance('com.sun.star.awt.UnoControlDialog', True) model = create_instance('com.sun.star.awt.UnoControlDialogModel', True) toolkit = create_instance('com.sun.star.awt.Toolkit', True) set_properties(model, properties) dlg.setModel(model) dlg.setVisible(False) dlg.createPeer(toolkit, None) return dlg def _get_type_control(self, name): types = { 'stardiv.Toolkit.UnoFixedTextControl': 'label', '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] def _init_controls(self): for control in self.obj.getControls(): tipo = self._get_type_control(control.ImplementationName) name = control.Model.Name control = get_custom_class(tipo, control) setattr(self, name, control) return @property def obj(self): return self._obj @property def model(self): return self._model @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 @property def images(self): return self._images @images.setter def images(self, value): self._images = value @property def height(self): return self.model.Height @height.setter def height(self, value): self.model.Height = value @property def width(self): return self.model.Width @width.setter def width(self, value): self.model.Width = value @property def color_on_focus(self): return self._color_on_focus @color_on_focus.setter def color_on_focus(self, value): global COLOR_ON_FOCUS COLOR_ON_FOCUS = get_color(value) self._color_on_focus = COLOR_ON_FOCUS @property def step(self): return self.model.Step @step.setter def step(self, value): self.model.Step = value @property def events(self): return self._events @events.setter def events(self, controllers): self._events = controllers self._connect_listeners() def _connect_listeners(self): for control in self.obj.getControls(): add_listeners(self._events, control, control.Model.Name) return def open(self): return self.obj.execute() def close(self, value=0): return self.obj.endDialog(value) def _get_control_model(self, 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', 'pages': 'com.sun.star.awt.UnoMultiPageModel', } return services[control] def _set_column_model(self, 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(self, image): if exists_path(image): return _path_url(image) if not self.id_extension: return '' path = get_path_extension(self.id_extension) path = join(path, self.images, image) return _path_url(path) 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'] = 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 == '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) name = properties['Name'] self.model.insertByName(name, model) 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 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), properties.get('Y', 0), properties.get('Width', 500), properties.get('Height', 500), ) self._title = properties.get('Title', TITLE) self._create_frame(ps) self._create_container(ps) self._create_subcontainer(ps) # ~ self._create_splitter(ps) return def _create_frame(self, ps): service = 'com.sun.star.frame.TaskCreator' tc = create_instance(service, True) self._frame = tc.createInstanceWithArguments(( NamedValue('FrameName', 'EasyMacroWin'), NamedValue('PosSize', Rectangle(*ps)), )) self._window = self._frame.getContainerWindow() self._toolkit = self._window.getToolkit() desktop = get_desktop() self._frame.setCreator(desktop) desktop.getFrames().append(self._frame) self._frame.Title = self._title return def _create_container(self, ps): # ~ toolkit = self._window.getToolkit() service = 'com.sun.star.awt.UnoControlContainer' self._container = create_instance(service, True) service = 'com.sun.star.awt.UnoControlContainerModel' model = create_instance(service, True) model.BackgroundColor = get_color(225, 225, 225) self._container.setModel(model) self._container.createPeer(self._toolkit, self._window) self._container.setPosSize(*ps, POSSIZE) 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', 'button': 'com.sun.star.awt.UnoControlButton', 'text': 'com.sun.star.awt.UnoControlEdit', 'listbox': 'com.sun.star.awt.UnoControlListBox', 'link': 'com.sun.star.awt.UnoControlFixedHyperlink', 'roadmap': 'com.sun.star.awt.UnoControlRoadmap', 'image': 'com.sun.star.awt.UnoControlImageControl', 'groupbox': 'com.sun.star.awt.UnoControlGroupBox', '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() 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) name = properties['Name'] 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 def _create_popupmenu(self, menus): menu = create_instance('com.sun.star.awt.PopupMenu', True) for i, m in enumerate(menus): label = m['label'] cmd = m.get('event', '') if not cmd: cmd = label.lower().replace(' ', '_') if label == '-': menu.insertSeparator(i) else: menu.insertItem(i, label, m.get('style', 0), i) menu.setCommand(i, cmd) # ~ menu.setItemImage(i, path?, True) menu.addMenuListener(EventsMenu(self.events)) return menu def _create_menu(self, menus): #~ https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1XMenu.html #~ nItemId specifies the ID of the menu item to be inserted. #~ aText specifies the label of the menu item. #~ nItemStyle 0 = Standard, CHECKABLE = 1, RADIOCHECK = 2, AUTOCHECK = 4 #~ nItemPos specifies the position where the menu item will be inserted. self._menu = create_instance('com.sun.star.awt.MenuBar', True) for i, m in enumerate(menus): self._menu.insertItem(i, m['label'], m.get('style', 0), i) cmd = m['label'].lower().replace(' ', '_') self._menu.setCommand(i, cmd) submenu = self._create_popupmenu(m['submenu']) self._menu.setPopupMenu(i, submenu) self._window.setMenuBar(self._menu) return def add_menu(self, menus): self._create_menu(menus) return def _add_listeners(self, control=None): if self.events is None: return controller = EventsWindow(self) self._window.addTopWindowListener(controller) self._window.addWindowListener(controller) self._container.addKeyListener(EventsKeyWindow(self)) return @property def name(self): return self._title.lower().replace(' ', '_') @property def events(self): return self._events @events.setter def events(self, value): self._events = value self._add_listeners() @property def width(self): return self._container.Size.Width @property def height(self): return self._container.Size.Height def open(self): self._window.setVisible(True) return def close(self): self._window.setMenuBar(None) self._window.dispose() self._frame.close(True) return # ~ Python >= 3.7 # ~ def __getattr__(name): def create_window(kwargs): return LOWindow(**kwargs) # ~ Export ok def get_file(init_dir='', multiple=False, filters=()): """ init_folder: folder default open multiple: True for multiple selected filters: Example ( ('XML', '*.xml'), ('TXT', '*.txt'), ) """ if not init_dir: init_dir = get_config_path() init_dir = _path_url(init_dir) file_picker = create_instance('com.sun.star.ui.dialogs.FilePicker') file_picker.setTitle(_('Select file')) file_picker.setDisplayDirectory(init_dir) file_picker.setMultiSelectionMode(multiple) path = '' if filters: file_picker.setCurrentFilter(filters[0][0]) for f in filters: file_picker.appendFilter(f[0], f[1]) if file_picker.execute(): path = _path_system(file_picker.getSelectedFiles()[0]) if multiple: path = [_path_system(f) for f in file_picker.getSelectedFiles()] return path # ~ Export ok def get_path(init_dir='', filters=()): """ Options: http://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1ui_1_1dialogs_1_1TemplateDescription.html filters: Example ( ('XML', '*.xml'), ('TXT', '*.txt'), ) """ if not init_dir: init_dir = get_config_path() init_dir = _path_url(init_dir) file_picker = create_instance('com.sun.star.ui.dialogs.FilePicker') file_picker.setTitle(_('Select file')) file_picker.setDisplayDirectory(init_dir) file_picker.initialize((2,)) if filters: file_picker.setCurrentFilter(filters[0][0]) for f in filters: file_picker.appendFilter(f[0], f[1]) path = '' if file_picker.execute(): path = _path_system(file_picker.getSelectedFiles()[0]) return path # ~ Export ok def get_dir(init_dir=''): folder_picker = create_instance('com.sun.star.ui.dialogs.FolderPicker') if not init_dir: init_dir = get_config_path() init_dir = _path_url(init_dir) folder_picker.setDisplayDirectory(init_dir) path = '' if folder_picker.execute(): path = _path_system(folder_picker.getDirectory()) return path # ~ Export ok def json_dumps(data): return json.dumps(data, indent=4, sort_keys=True) # ~ Export ok def json_loads(data): return json.loads(data) # ~ Export ok def get_file_size(path): return Path(path).stat().st_size # ~ Export ok def is_created(path): return is_file(path) and bool(get_file_size(path)) # ~ Export ok def zip_content(path): with zipfile.ZipFile(path) as z: names = z.namelist() return names def popen(command, stdin=None): try: proc = subprocess.Popen(shlex.split(command), shell=IS_WIN, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for line in proc.stdout: yield line.decode().rstrip() except Exception as e: error(e) yield (e.errno, e.strerror) def url_open(url, options={}, verify=True, json=False): data = '' err = '' req = Request(url) try: 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, err def run(command, wait=False): try: if wait: result = subprocess.check_output(command, shell=True) else: p = subprocess.Popen(shlex.split(command), stdin=None, stdout=None, stderr=None, close_fds=True) result, er = p.communicate() except subprocess.CalledProcessError as e: msg = ("%s\nrun [ERROR]: output = %s, error code = %s\n" % (command, e.output, e.returncode)) error(msg) return False if result is None: return True return result.decode() def _zippwd(source, target, pwd): if IS_WIN: return False if not exists_app('zip'): return False cmd = 'zip' opt = '-j ' args = "{} --password {} ".format(cmd, pwd) if isinstance(source, (tuple, list)): if not target: return False args += opt + target + ' ' + ' '.join(source) else: if is_file(source) and not target: target = replace_ext(source, 'zip') elif is_dir(source) and not target: target = join(PurePath(source).parent, '{}.zip'.format(PurePath(source).name)) opt = '-r ' args += opt + target + ' ' + source result = run(args, True) if not result: return False return is_created(target) # ~ Export ok def zip_files(source, target='', mode='w', pwd=''): if pwd: return _zippwd(source, target, pwd) if isinstance(source, (tuple, list)): if not target: return False with zipfile.ZipFile(target, mode, compression=zipfile.ZIP_DEFLATED) as z: for path in source: _, name, _, _ = get_info_path(path) z.write(path, name) return is_created(target) if is_file(source): if not target: target = replace_ext(source, 'zip') z = zipfile.ZipFile(target, mode, compression=zipfile.ZIP_DEFLATED) _, name, _, _ = get_info_path(source) z.write(source, name) z.close() return is_created(target) if not target: target = join( PurePath(source).parent, '{}.zip'.format(PurePath(source).name)) z = zipfile.ZipFile(target, mode, compression=zipfile.ZIP_DEFLATED) root_len = len(os.path.abspath(source)) for root, dirs, files in os.walk(source): relative = os.path.abspath(root)[root_len:] for f in files: fullpath = join(root, f) file_name = join(relative, f) z.write(fullpath, file_name) z.close() return is_created(target) # ~ Export ok def unzip(source, path='', members=None, pwd=None): if not path: path, _, _, _ = get_info_path(source) with zipfile.ZipFile(source) as z: if not pwd is None: pwd = pwd.encode() if isinstance(members, str): members = (members,) z.extractall(path, members=members, pwd=pwd) return True # ~ Export ok def merge_zip(target, zips): try: with zipfile.ZipFile(target, 'w', compression=zipfile.ZIP_DEFLATED) as t: for path in zips: with zipfile.ZipFile(path, compression=zipfile.ZIP_DEFLATED) as s: for name in s.namelist(): t.writestr(name, s.open(name).read()) except Exception as e: error(e) return False return True def get_size_screen(): if IS_WIN: user32 = ctypes.windll.user32 res = '{}x{}'.format(user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)) else: args = 'xrandr | grep "*" | cut -d " " -f4' res = run(args, True) return res.strip() # ~ Export ok def get_epoch(): n = now() return int(time.mktime(n.timetuple())) # ~ Export ok def start(): global _start _start = now() log.info(_start) return # ~ Export ok def end(): global _start e = now() return str(e - _start).split('.')[0] # ~ Export ok def render(template, data): s = Template(template) return s.safe_substitute(**data) # ~ Export ok def format(template, data): """ https://pyformat.info/ """ if isinstance(data, (str, int, float)): # ~ print(template.format(data)) return template.format(data) if isinstance(data, (Time, Date, DateTime)): return template.format(_to_date(data)) if isinstance(data, tuple) and isinstance(data[0], tuple): data = {r[0]: _to_date(r[1]) for r in data} return template.format(**data) data = [_to_date(v) for v in data] result = template.format(*data) return result