Embed py in documents
This commit is contained in:
parent
14630c1bd7
commit
6e101413b9
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue