#!/usr/bin/env python3 # == Rapid Develop Macros in LibreOffice == # ~ This file is part of ZAZ. # ~ ZAZ is free software: you can redistribute it and/or modify # ~ it under the terms of the GNU General Public License as published by # ~ the Free Software Foundation, either version 3 of the License, or # ~ (at your option) any later version. # ~ ZAZ is distributed in the hope that it will be useful, # ~ but WITHOUT ANY WARRANTY; without even the implied warranty of # ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # ~ GNU General Public License for more details. # ~ You should have received a copy of the GNU General Public License # ~ along with ZAZ. If not, see . import getpass import logging import platform import sys import tempfile import threading import time from functools import wraps import uno from com.sun.star.beans import PropertyValue from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS from com.sun.star.awt.MessageBoxResults import YES from com.sun.star.awt.PosSize import POSSIZE, SIZE from com.sun.star.awt import Size from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA FILE_NAME_DEBUG = 'debug.log' MSG_LANG = { 'es': { 'OK': 'Aceptar', 'Cancel': 'Cancelar', } } FORMAT = '%(asctime)s - %(levelname)s - %(message)s' DATE = '%d/%m/%Y %H:%M:%S' LEVEL_ERROR = logging.getLevelName(logging.ERROR) LEVEL_DEBUG = logging.getLevelName(logging.DEBUG) LEVEL_INFO = logging.getLevelName(logging.INFO) logging.addLevelName(logging.ERROR, f'\033[1;41m{LEVEL_ERROR}\033[1;0m') logging.addLevelName(logging.DEBUG, f'\x1b[33m{LEVEL_DEBUG}\033[1;0m') logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m') logging.basicConfig(level=logging.DEBUG, format=FORMAT, datefmt=DATE) log = logging.getLogger(__name__) OBJ_CELL = 'ScCellObj' OBJ_RANGE = 'ScCellRangeObj' OBJ_RANGES = 'ScCellRangesObj' CTX = uno.getComponentContext() SM = CTX.getServiceManager() def create_instance(name, with_context=False): if with_context: instance = SM.createInstanceWithContext(name, CTX) else: instance = SM.createInstance(name) return instance def _get_config(key, node_name): name = 'com.sun.star.configuration.ConfigurationProvider' service = 'com.sun.star.configuration.ConfigurationAccess' cp = create_instance(name, True) node = PropertyValue(Name='nodepath', Value=node_name) try: ca = cp.createInstanceWithArguments(service, (node,)) if ca and (ca.hasByName(key)): data = ca.getPropertyValue(key) return data except Exception as e: log.error(e) return '' OS = sys.platform USER = getpass.getuser() PC = platform.node() LANGUAGE = _get_config('ooLocale', 'org.openoffice.Setup/L10N/') NAME = TITLE = _get_config('ooName', 'org.openoffice.Setup/Product') VERSION = _get_config('ooSetupVersion', 'org.openoffice.Setup/Product') DESKTOP = create_instance('com.sun.star.frame.Desktop', True) INFO_DEBUG = '{}\n\n{}\n\n{}'.format( sys.version, platform.platform(), '\n'.join(sys.path)) def mri(obj): m = create_instance('mytools.Mri') if m is None: msg = 'Extension MRI not found' error(msg) return m.inspect(obj) return def debug(info): log.debug(info) return def error(info): log.error(info) return def catch_exception(f): @wraps(f) def func(*args, **kwargs): try: return f(*args, **kwargs) except Exception as e: log.error(f.__name__, exc_info=True) return func def run_in_thread(fn): def run(*k, **kw): t = threading.Thread(target=fn, args=k, kwargs=kw) t.start() return t return run def _(msg): L = LANGUAGE.split('-')[0] if L == 'en': return msg if not L in MSG_LANG: return msg return MSG_LANG[L][msg] def msgbox(message, title=TITLE, buttons=MSG_BUTTONS.BUTTONS_OK, type_msg='infobox'): """ Create message box type_msg: infobox, warningbox, errorbox, querybox, messbox http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1XMessageBoxFactory.html """ toolkit = create_instance('com.sun.star.awt.Toolkit') parent = toolkit.getDesktopWindow() mb = toolkit.createMessageBox(parent, type_msg, buttons, title, str(message)) return mb.execute() def question(message, title=TITLE): res = msgbox(message, title, MSG_BUTTONS.BUTTONS_YES_NO, 'querybox') return res == YES def warning(message, title=TITLE): return msgbox(message, title, type_msg='warningbox') def errorbox(message, title=TITLE): return msgbox(message, title, type_msg='errorbox') def get_temp_file(): return tempfile.NamedTemporaryFile() def _path_url(path): if path.startswith('file://'): return path return uno.systemPathToFileUrl(path) # ~ Custom classes class LOCellRange(object): def __init__(self, obj): self._obj = obj self._init_values() def __enter__(self): return self def __exit__(self, *args): pass def _init_values(self): 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 type_content(self): return self._type_content @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)): self.obj.setValue(data) def offset(self, col=1, row=0): a = self.address col = a.Column + col row = a.Row + row return LOCellRange(self.obj.Spreadsheet[row,col]) @property def sheet(self): return self.obj.Spreadsheet @property def draw_page(self): return self.sheet.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 def add_image(self, path, **kwargs): s = self.obj.Size w = kwargs.get('width', s.Width) h = kwargs.get('Height', s.Height) doc = get_document() img = doc.createInstance('com.sun.star.drawing.GraphicObjectShape') img.GraphicURL = _path_url(path) self.draw_page.add(img) img.Anchor = self.obj img.setSize(Size(w, h)) return # ~ Python >= 3.7 # ~ def __getattr__(name): def get_document(): doc = None try: doc = DESKTOP.getCurrentComponent() except Exception as e: log.error(e) return doc def get_selection(): obj = None try: obj = get_document().getCurrentSelection() except Exception as e: log.error(e) return obj def get_cell(*args): sel = get_selection() if sel.ImplementationName == OBJ_RANGE: sel = sel[0,0] elif sel.ImplementationName == OBJ_RANGES: sel = sel[0][0,0] return LOCellRange(sel)