From 6e101413b97f84d357c521ec76c90e8c9715d80f Mon Sep 17 00:00:00 2001 From: Mauricio Baeza Date: Fri, 11 Sep 2020 21:54:38 -0500 Subject: [PATCH] Embed py in documents --- source/easymacro.py | 12 - source/easymacro2.py | 689 ++++++++++++++++++++++++++++++++++++++++--- source/zaz.py | 20 +- 3 files changed, 655 insertions(+), 66 deletions(-) diff --git a/source/easymacro.py b/source/easymacro.py index 1df04cf..56faf1f 100644 --- a/source/easymacro.py +++ b/source/easymacro.py @@ -950,22 +950,10 @@ class LOImage(object): def __init__(self, obj): self._obj = obj - @property - def obj(self): - return self._obj - @property def address(self): return self.obj.Anchor.AbsoluteName - @property - def name(self): - return self.obj.Name - - @property - def mimetype(self): - return self.obj.Bitmap.MimeType - @property def url(self): return _path_system(self.obj.URL) diff --git a/source/easymacro2.py b/source/easymacro2.py index 1d0af36..e913b91 100644 --- a/source/easymacro2.py +++ b/source/easymacro2.py @@ -4,6 +4,8 @@ # ~ This file is part of ZAZ. +# ~ https://gitlab.com/mauriciobaeza/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 @@ -20,9 +22,11 @@ import datetime import getpass +import gettext import logging import os import platform +import shlex import socket import subprocess import sys @@ -39,6 +43,9 @@ import unohelper from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS from com.sun.star.awt.MessageBoxResults import YES from com.sun.star.awt import Rectangle +from com.sun.star.awt import Key, KeyModifier, KeyEvent +from com.sun.star.container import NoSuchElementException + from com.sun.star.beans import PropertyValue, NamedValue from com.sun.star.sheet import TableFilterField from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA @@ -48,6 +55,7 @@ from com.sun.star.awt import XActionListener from com.sun.star.lang import XEventListener from com.sun.star.awt import XMouseListener from com.sun.star.awt import XMouseMotionListener +from com.sun.star.awt import XFocusListener # ~ https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1awt_1_1FontUnderline.html from com.sun.star.awt import FontUnderline @@ -57,10 +65,7 @@ try: from peewee import Database, DateTimeField, DateField, TimeField, \ __exception_wrapper__ except ImportError as e: - Database = object - DateField = object - TimeField = object - DateTimeField = object + Database = DateField = TimeField = DateTimeField = object print('Install peewee') @@ -84,6 +89,7 @@ IMPRESS = 'impress' BASE = 'base' MATH = 'math' BASIC = 'basic' +MAIN = 'main' TYPE_DOC = { CALC: 'com.sun.star.sheet.SpreadsheetDocument', WRITER: 'com.sun.star.text.TextDocument', @@ -92,7 +98,7 @@ TYPE_DOC = { BASE: 'com.sun.star.sdb.DocumentDataSource', MATH: 'com.sun.star.formula.FormulaProperties', BASIC: 'com.sun.star.script.BasicIDE', - 'main': 'com.sun.star.frame.StartModule', + MAIN: 'com.sun.star.frame.StartModule', } OBJ_CELL = 'ScCellObj' @@ -107,6 +113,11 @@ class FilterOperator(IntEnum): EQUAL = 2 NOT_EQUAL = 3 +# ~ https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1awt_1_1UnoControlEditModel.html#a54d3ff280d892218d71e667f81ce99d4 +class Border(IntEnum): + NO_BORDER = 0 + BORDER = 1 + SIMPLE = 2 OS = platform.system() IS_WIN = OS == 'Windows' @@ -116,9 +127,53 @@ PC = platform.node() DESKTOP = os.environ.get('DESKTOP_SESSION', '') INFO_DEBUG = f"{sys.version}\n\n{platform.platform()}\n\n" + '\n'.join(sys.path) +_MACROS = {} SECONDS_DAY = 60 * 60 * 24 -_MACROS = {} +DIR = { + 'images': 'images', + 'locales': 'locales', +} +MIMETYPE = 'png' +MODIFIERS = { + 'shift': KeyModifier.SHIFT, + 'ctrl': KeyModifier.MOD1, + 'alt': KeyModifier.MOD2, + 'ctrlmac': KeyModifier.MOD3, +} + +# ~ Menus +NODE_MENUBAR = 'private:resource/menubar/menubar' +MENUS = { + 'file': '.uno:PickList', + 'tools': '.uno:ToolsMenu', + 'help': '.uno:HelpMenu', + 'windows': '.uno:WindowList', + 'edit': '.uno:EditMenu', + 'view': '.uno:ViewMenu', + 'insert': '.uno:InsertMenu', + 'format': '.uno:FormatMenu', + 'styles': '.uno:FormatStylesMenu', + 'sheet': '.uno:SheetMenu', + 'data': '.uno:DataMenu', + 'table': '.uno:TableMenu', + 'form': '.uno:FormatFormMenu', + 'page': '.uno:PageMenu', + 'shape': '.uno:ShapeMenu', + 'slide': '.uno:SlideMenu', + 'show': '.uno:SlideShowMenu', +} + +MESSAGES = { + 'es': { + 'OK': 'Aceptar', + 'Cancel': 'Cancelar', + 'Select file': 'Seleccionar archivo', + 'Incorrect user or password': 'Nombre de usuario o contraseña inválidos', + 'Allow less secure apps in GMail': 'Activa: Permitir aplicaciones menos segura en GMail', + } +} + CTX = uno.getComponentContext() SM = CTX.getServiceManager() @@ -202,6 +257,17 @@ def inspect(obj: Any) -> None: return +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 now(only_time=False): now = datetime.datetime.now() if only_time: @@ -213,6 +279,16 @@ def today(): return datetime.date.today() +def _(msg): + if LANG == 'en': + return msg + + if not LANG in MESSAGES: + return msg + + return MESSAGES[LANG][msg] + + def msgbox(message, title=TITLE, buttons=MSG_BUTTONS.BUTTONS_OK, type_msg='infobox'): """ Create message box type_msg: infobox, warningbox, errorbox, querybox, messbox @@ -258,6 +334,19 @@ def _get_class_doc(obj: Any) -> Any: return classes[type_doc](obj) +def _get_class_uno(obj: Any) -> Any: + classes = dict( + SwXTextGraphicObject = LOImage, + SvxShapeText = LOImage, + ) + name = obj.ImplementationName + print(f'ImplementationName = {name}') + instance = obj + if name in classes: + instance = classes[name](obj) + return instance + + def dict_to_property(values: dict, uno_any: bool=False): ps = tuple([PropertyValue(Name=n, Value=v) for n, v in values.items()]) if uno_any: @@ -391,6 +480,17 @@ def call_macro(args, in_thread=False): return result +def run(command, capture=False): + result = subprocess.run(shlex.split(command), + capture_output=capture, text=True).stdout + return result + + +def sleep(seconds): + time.sleep(seconds) + return + + class TimerThread(threading.Thread): def __init__(self, event, seconds, macro): @@ -422,6 +522,28 @@ def stop_timer(name): return +def install_locales(path, domain='base', dir_locales=DIR['locales']): + path_locales = _P.join(_P(path).path, dir_locales) + try: + lang = gettext.translation(domain, path_locales, languages=[LANG]) + lang.install() + _ = lang.gettext + except Exception as e: + from gettext import gettext as _ + error(e) + return _ + + +def _export_image(obj, args): + name = 'com.sun.star.drawing.GraphicExportFilter' + exporter = create_instance(name) + path = _P.to_system(args['URL']) + args = dict_to_property(args) + exporter.setSourceDocument(obj) + exporter.filter(args) + return _P.exists(path) + + class LOBaseObject(object): def __init__(self, obj): @@ -445,6 +567,54 @@ class LOBaseObject(object): return self._obj +class LOImage(object): + TYPE = { + 'png': 'image/png', + 'jpg': 'image/jpeg', + } + + def __init__(self, obj): + self._obj = obj + + @property + def obj(self): + return self._obj + + @property + def name(self): + return self.obj.Name or 'img' + + @property + def mimetype(self): + return self.obj.Bitmap.MimeType + + def save(self, path, mimetype=MIMETYPE): + p = _P(path) + if _P.is_dir(path): + name = self.name + else: + path = p.path + name = p.name + + path = _P.join(path, f'{name}.{mimetype.lower()}') + args = dict( + URL = _P.to_url(path), + MimeType = self.TYPE[mimetype], + ) + if not _export_image(self.obj, args): + path = '' + + # ~ size = len(self.obj.Bitmap.DIB) + # ~ data = self.obj.GraphicStream.readBytes((), size) + # ~ data = data[-1].value + + # ~ data = self.obj.Bitmap.DIB.value + # ~ data = self.obj.Graphic.DIB.value + + # ~ _P.save_bin(path, data) + return path + + class LODocument(object): def __init__(self, obj): @@ -519,7 +689,7 @@ class LODocument(object): @property def selection(self): sel = self.obj.CurrentSelection - return sel + return _get_class_uno(sel) def create_instance(self, name): obj = self.obj.createInstance(name) @@ -534,10 +704,6 @@ class LODocument(object): call_dispatch(self.frame, '.uno:Copy') return - # ~ def paste(self): - # ~ call_dispatch(self.frame, '.uno:Paste') - # ~ return - def paste(self): sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard') transferable = sc.getContents() @@ -909,8 +1075,10 @@ class LOCalcRange(object): @value.setter def value(self, data): if isinstance(data, str): - if data[0] == '=': + print(isinstance(data, str), data[0]) + if data[0] in '=+-': self.obj.setFormula(data) + print('Set Formula') else: self.obj.setString(data) elif isinstance(data, (int, float, bool)): @@ -1022,6 +1190,15 @@ class LODrawImpress(LODocument): def __init__(self, obj): super().__init__(obj) + @property + def selection(self): + sel = self.obj.CurrentSelection[0] + return _get_class_uno(sel) + + def paste(self): + call_dispatch(self.frame, '.uno:Paste') + return self.selection + class LODraw(LODrawImpress): @@ -1195,30 +1372,21 @@ class LOBase(object): def __init__(self, obj, args={}): self._obj = obj self._type = BASE - self._path = args.get('path', '') self._dbc = create_instance('com.sun.star.sdb.DatabaseContext') self._rows_affected = 0 - if self._path: - self._name = Path(self._path).name - path_url = _path_url(self._path) + path = args.get('path', '') + self._path = _P(path) + self._name = self._path.name + if _P.exists(path): + if not self.is_registered: + self.register() + db = self._dbc.getByName(self.name) + else: db = self._dbc.createInstance() db.URL = 'sdbc:embedded:firebird' - db.DatabaseDocument.storeAsURL(path_url, ()) + db.DatabaseDocument.storeAsURL(self._path.url, ()) self.register() - self._obj = db - else: - self._name = self._obj - if Path(self._name).exists(): - self._path = self._name - self._name = Path(self._path).name - if self.is_registered: - db = self._dbc.getByName(self.name) - self._path = _path_system(self._dbc.getDatabaseLocation(self.name)) - self._obj = db - else: - path_url = _path_url(self._path) - self._dbc.registerDatabaseLocation(self.name, path_url) - db = self._dbc.getByName(self.name) + self._obj = db self._con = db.getConnection('', '') def __contains__(self, item): @@ -1234,7 +1402,7 @@ class LOBase(object): @property def path(self): - return self._path + return str(self._path) @property def is_registered(self): @@ -1251,8 +1419,7 @@ class LOBase(object): def register(self): if not self.is_registered: - path_url = _path_url(self._path) - self._dbc.registerDatabaseLocation(self.name, path_url) + self._dbc.registerDatabaseLocation(self.name, self._path.url) return def revoke(self, name): @@ -1359,11 +1526,15 @@ class LODocs(object): LODocs._desktop = self._desktop def __getitem__(self, index): + doc = None for i, doc in enumerate(self._desktop.Components): if isinstance(index, int) and i == index: - return _get_class_doc(doc) + doc = _get_class_doc(doc) + break elif isinstance(index, str) and doc.Title == index: - return _get_class_doc(doc) + doc = _get_class_doc(doc) + break + return doc def __contains__(self, item): doc = self[item] @@ -1422,15 +1593,15 @@ class LODocs(object): return _get_class_doc(doc) def connect(self, path): - return LOBase(path) + return LOBase(None, {'path': path}) def _add_listeners(events, control, name=''): listeners = { 'addActionListener': EventsButton, 'addMouseListener': EventsMouse, + 'addFocusListener': EventsFocus, # ~ 'addItemListener': EventsItem, - # ~ 'addFocusListener': EventsFocus, # ~ 'addKeyListener': EventsKey, # ~ 'addTabListener': EventsTab, } @@ -1550,6 +1721,30 @@ class EventsButton(EventsListenerBase, XActionListener): return +class EventsFocus(EventsListenerBase, XFocusListener): + CONTROLS = ( + 'stardiv.Toolkit.UnoControlEditModel', + ) + + def __init__(self, controller, name): + super().__init__(controller, name) + + def focusGained(self, event): + service = event.Source.Model.ImplementationName + # ~ print('Focus enter', service) + if service in self.CONTROLS: + obj = event.Source.Model + obj.BackgroundColor = COLOR_ON_FOCUS + return + + def focusLost(self, event): + service = event.Source.Model.ImplementationName + if service in self.CONTROLS: + obj = event.Source.Model + obj.BackgroundColor = -1 + return + + # ~ BorderColor = ? # ~ FontStyleName = ? # ~ HelpURL = ? @@ -1879,12 +2074,31 @@ class UnoCheck(UnoBaseObject): self.model.TriState = value +# ~ https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1awt_1_1UnoControlEditModel.html +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 + + UNO_CLASSES = { 'label': UnoLabel, 'link': UnoLabelLink, 'button': UnoButton, 'radio': UnoRadio, 'check': UnoCheck, + 'text': UnoText, } @@ -1895,11 +2109,11 @@ class LODialog(object): 'button': 'com.sun.star.awt.UnoControlButtonModel', 'radio': 'com.sun.star.awt.UnoControlRadioButtonModel', 'check': 'com.sun.star.awt.UnoControlCheckBoxModel', + 'text': 'com.sun.star.awt.UnoControlEditModel', + # ~ 'grid': 'com.sun.star.awt.grid.UnoControlGridModel', # ~ 'groupbox': 'com.sun.star.awt.UnoControlGroupBoxModel', - # ~ 'text': 'com.sun.star.awt.UnoControlEditModel', # ~ 'listbox': 'com.sun.star.awt.UnoControlListBoxModel', # ~ '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', @@ -1912,6 +2126,7 @@ class LODialog(object): self._events = None self._modal = True self._controls = {} + self._color_on_focus = COLOR_ON_FOCUS def _create(self, args): service = 'com.sun.star.awt.DialogProvider' @@ -1973,6 +2188,13 @@ class LODialog(object): self._events = controllers(self) self._connect_listeners() + @property + def color_on_focus(self): + return self._color_on_focus + @color_on_focus.setter + def color_on_focus(self, value): + self._color_on_focus = get_color(value) + def _connect_listeners(self): for control in self.obj.Controls: _add_listeners(self.events, control, control.Model.Name) @@ -2062,30 +2284,336 @@ class LOCells(object): return LODocs().active.active[index] +class LOShortCut(object): +# ~ getKeyEventsByCommand + + def __init__(self, app): + self._app = app + self._scm = None + self._init_values() + + def _init_values(self): + name = 'com.sun.star.ui.GlobalAcceleratorConfiguration' + instance = 'com.sun.star.ui.ModuleUIConfigurationManagerSupplier' + service = TYPE_DOC[self._app] + manager = create_instance(instance, True) + uicm = manager.getUIConfigurationManager(service) + self._scm = uicm.ShortCutManager + return + + def __contains__(self, item): + cmd = self._get_command(item) + return bool(cmd) + + def _get_key_event(self, command): + events = self._scm.AllKeyEvents + for event in events: + cmd = self._scm.getCommandByKeyEvent(event) + if cmd == command: + break + return event + + def _to_key_event(self, shortcut): + key_event = KeyEvent() + keys = shortcut.split('+') + for v in keys[:-1]: + key_event.Modifiers += MODIFIERS[v.lower()] + key_event.KeyCode = getattr(Key, keys[-1].upper()) + return key_event + + def _get_command(self, shortcut): + command = '' + key_event = self._to_key_event(shortcut) + try: + command = self._scm.getCommandByKeyEvent(key_event) + except NoSuchElementException: + debug(f'No exists: {shortcut}') + return command + + def add(self, shortcut, command): + if isinstance(command, dict): + command = _get_url_script(command) + key_event = self._to_key_event(shortcut) + self._scm.setKeyEvent(key_event, command) + self._scm.store() + return + + def reset(self): + self._scm.reset() + self._scm.store() + return + + def remove(self, shortcut): + key_event = self._to_key_event(shortcut) + try: + self._scm.removeKeyEvent(key_event) + self._scm.store() + except NoSuchElementException: + debug(f'No exists: {shortcut}') + return + + def remove_by_command(self, command): + if isinstance(command, dict): + command = _get_url_script(command) + try: + self._scm.removeCommandFromAllKeyEvents(command) + self._scm.store() + except NoSuchElementException: + debug(f'No exists: {command}') + return + + +class LOShortCuts(object): + + def __getitem__(self, index): + return LOShortCut(index) + + +class LOMenu(object): + + def __init__(self, app): + self._app = app + self._ui = None + self._pymenus = None + self._menu = None + self._menus = self._get_menus() + + def __getitem__(self, index): + if isinstance(index, int): + self._menu = self._menus[index] + else: + for menu in self._menus: + cmd = menu.get('CommandURL', '') + if MENUS[index.lower()] == cmd: + self._menu = menu + break + line = self._menu.get('CommandURL', '') + line += self._get_submenus(self._menu['ItemDescriptorContainer']) + return line + + def _get_menus(self): + instance = 'com.sun.star.ui.ModuleUIConfigurationManagerSupplier' + service = TYPE_DOC[self._app] + manager = create_instance(instance, True) + self._ui = manager.getUIConfigurationManager(service) + self._pymenus = self._ui.getSettings(NODE_MENUBAR, True) + data = [] + for menu in self._pymenus: + data.append(data_to_dict(menu)) + return data + + def _get_info(self, menu): + line = menu.get('CommandURL', '') + line += self._get_submenus(menu['ItemDescriptorContainer']) + return line + + def _get_submenus(self, menu, level=1): + line = '' + for i, v in enumerate(menu): + data = data_to_dict(v) + cmd = data.get('CommandURL', '----------') + line += f'\n{" " * level}├─ ({i}) {cmd}' + submenu = data.get('ItemDescriptorContainer', None) + if not submenu is None: + line += self._get_submenus(submenu, level + 1) + return line + + def __str__(self): + info = '\n'.join([self._get_info(m) for m in self._menus]) + return info + + def _get_index_menu(self, menu, command): + index = -1 + for i, v in enumerate(menu): + data = data_to_dict(v) + cmd = data.get('CommandURL', '') + if cmd == command: + index = i + break + return index + + def insert(self, name, args): + idc = None + replace = False + command = args['CommandURL'] + label = args['Label'] + + self[name] + menu = self._menu['ItemDescriptorContainer'] + submenu = args.get('Submenu', False) + if submenu: + idc = self._ui.createSettings() + + index = self._get_index_menu(menu, command) + if index == -1: + if 'Index' in args: + index = args['Index'] + else: + index = self._get_index_menu(menu, args['After']) + 1 + else: + replace = True + + data = dict ( + CommandURL = command, + Label = label, + Style = 0, + Type = 0, + ItemDescriptorContainer = idc, + ) + self._save(menu, data, index, replace) + self._insert_submenu(idc, submenu) + return + + def _get_command(self, args): + shortcut = args.get('ShortCut', '') + cmd = args['CommandURL'] + if isinstance(cmd, dict): + cmd = _get_url_script(cmd) + if shortcut: + LOShortCut(self._app).add(shortcut, cmd) + return cmd + + def _insert_submenu(self, parent, menus): + for i, v in enumerate(menus): + submenu = v.pop('Submenu', False) + if submenu: + idc = self._ui.createSettings() + v['ItemDescriptorContainer'] = idc + v['Type'] = 0 + if v['Label'] == '-': + v['Type'] = 1 + else: + v['CommandURL'] = self._get_command(v) + self._save(parent, v, i) + if submenu: + self._insert_submenu(idc, submenu) + return + + def remove(self, name, command): + self[name] + menu = self._menu['ItemDescriptorContainer'] + index = self._get_index_menu(menu, command) + if index > -1: + uno.invoke(menu, 'removeByIndex', (index,)) + self._ui.replaceSettings(NODE_MENUBAR, self._pymenus) + self._ui.store() + return + + def _save(self, menu, properties, index, replace=False): + properties = dict_to_property(properties, True) + if replace: + uno.invoke(menu, 'replaceByIndex', (index, properties)) + else: + uno.invoke(menu, 'insertByIndex', (index, properties)) + self._ui.replaceSettings(NODE_MENUBAR, self._pymenus) + self._ui.store() + return + + +class LOMenus(object): + + def __getitem__(self, index): + return LOMenu(index) + + +class classproperty: + def __init__(self, method=None): + self.fget = method + + def __get__(self, instance, cls=None): + return self.fget(cls) + + def getter(self, method): + self.fget = method + return self + + class Paths(object): + def __init__(self, path=''): + self._path = Path(path) + + @property + def path(self): + return str(self._path.parent) + + @property + def file_name(self): + return self._path.name + + @property + def name(self): + return self._path.stem + + @property + def ext(self): + return self._path.suffix + + @property + def url(self): + return self._path.as_uri() + + @classproperty + def home(self): + return str(Path.home()) + @classmethod def exists(cls, path): return Path(path).exists() + @classmethod + def is_dir(cls, path): + return Path(path).is_dir() + + @classmethod + def join(cls, *paths): + return str(Path(paths[0]).joinpath(paths[1])) + + @classmethod + def save(cls, path, data, encoding='utf-8'): + result = bool(Path(path).write_text(data, encoding=encoding)) + return result + + @classmethod + def save_bin(cls, path, data): + result = bool(Path(path).write_bytes(data)) + return result + + @classmethod + def to_url(cls, path): + if not path.startswith('file://'): + path = Path(path).as_uri() + return path + + @classmethod + def to_system(cls, path): + if path.startswith('file://'): + path = str(Path(uno.fileUrlToSystemPath(path)).resolve()) + return path +_P = Paths + def __getattr__(name): if name == 'active': - return docs.active + return LODocs().active if name == 'active_sheet': - return docs.active.active + return LODocs().active.active if name == 'selection': - return docs.active.selection + return LODocs().active.selection if name in ('rectangle', 'pos_size'): return Rectangle() if name == 'paths': - return Paths() + return Paths if name == 'docs': return LODocs() if name == 'sheets': return LOSheets() if name == 'cells': return LOCells() + if name == 'menus': + return LOMenus() + if name == 'shortcuts': + return LOShortCuts() raise AttributeError(f"module '{__name__}' has no attribute '{name}'") @@ -2093,6 +2621,79 @@ def create_dialog(args): return LODialog(args) +def inputbox(message, default='', title=TITLE, echochar=''): + + class ControllersInput(object): + + def __init__(self, dlg): + self.d = dlg + + def cmd_ok_action(self, event): + self.d.close(1) + return + + args = { + 'Title': title, + 'Width': 200, + 'Height': 80, + } + dlg = LODialog(args) + dlg.events = ControllersInput + + args = { + 'Type': 'Label', + 'Name': 'lbl_msg', + 'Label': message, + 'Width': 140, + 'Height': 50, + 'X': 5, + 'Y': 5, + 'MultiLine': True, + 'Border': 1, + } + dlg.add_control(args) + + args = { + 'Type': 'Text', + 'Name': 'txt_value', + 'Text': default, + 'Width': 190, + 'Height': 15, + } + if echochar: + args['EchoChar'] = ord(echochar[0]) + dlg.add_control(args) + dlg.txt_value.move(dlg.lbl_msg) + + args = { + 'Type': 'button', + 'Name': 'cmd_ok', + 'Label': _('OK'), + 'Width': 40, + 'Height': 15, + 'DefaultButton': True, + 'PushButtonType': 1, + } + dlg.add_control(args) + dlg.cmd_ok.move(dlg.lbl_msg, 10, 0) + + args = { + 'Type': 'button', + 'Name': 'cmd_cancel', + 'Label': _('Cancel'), + 'Width': 40, + 'Height': 15, + 'PushButtonType': 2, + } + dlg.add_control(args) + dlg.cmd_cancel.move(dlg.cmd_ok) + + if dlg.open(): + return dlg.txt_value.value + + return '' + + def get_fonts(): toolkit = create_instance('com.sun.star.awt.Toolkit') device = toolkit.createScreenCompatibleDevice(0, 0) diff --git a/source/zaz.py b/source/zaz.py index 1210718..1d40e32 100644 --- a/source/zaz.py +++ b/source/zaz.py @@ -19,6 +19,7 @@ import argparse import os +import py_compile import re import sys import zipfile @@ -55,6 +56,7 @@ class LiboXML(object): } TYPES = { 'py': 'application/vnd.sun.star.uno-component;type=Python', + 'pyc': 'application/binary', 'zip': 'application/binary', 'xcu': 'application/vnd.sun.star.configuration-data', 'rdb': 'application/vnd.sun.star.uno-typelibrary;type=RDB', @@ -121,8 +123,8 @@ class LiboXML(object): def parse_manifest(self, data): ET.register_namespace('manifest', self.NS_MANIFEST['manifest']) self._manifest = ET.fromstring(data) - data = {'xmlns:loext': self.NS_MANIFEST['xmlns:loext']} - self._manifest.attrib.update(**data) + attr = {'xmlns:loext': self.NS_MANIFEST['xmlns:loext']} + self._manifest.attrib.update(**attr) self._clean('manifest', self._manifest) return @@ -615,8 +617,8 @@ def _get_info_path(path): def _zip_embed(source, files): PATH = 'Scripts/python/' - EASYMACRO = 'easymacro.py' - FILE_ZIP = 'easymacro.zip' + EASYMACRO = 'easymacro2.py' + FILE_PYC = 'easymacro.pyc' p, f, name, e = _get_info_path(source) now = datetime.now().strftime('_%Y%m%d_%H%M%S') @@ -624,12 +626,10 @@ def _zip_embed(source, files): copyfile(source, path_source) target = source - with zipfile.ZipFile(FILE_ZIP, mode='w', compression=zipfile.ZIP_DEFLATED) as zf: - zf.write(EASYMACRO) - + py_compile.compile(EASYMACRO, FILE_PYC) xml = LiboXML() - path_easymacro = PATH + FILE_ZIP + path_easymacro = PATH + FILE_PYC names = [f[1] for f in files] + [path_easymacro] nodes = [] with zipfile.ZipFile(target, 'w', compression=zipfile.ZIP_DEFLATED) as zt: @@ -648,14 +648,14 @@ def _zip_embed(source, files): data.append(name) zt.write(path, name) - zt.write(FILE_ZIP, path_easymacro) + zt.write(FILE_PYC, path_easymacro) data.append(path_easymacro) xml.parse_manifest(xml_manifest) xml_manifest = xml.add_data_manifest(data) zt.writestr(path_manifest, xml_manifest) - os.unlink(FILE_ZIP) + os.unlink(FILE_PYC) return