Add support for locales
This commit is contained in:
parent
614d80e479
commit
358937cd19
|
@ -0,0 +1,14 @@
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
|
||||||
|
*.log
|
||||||
|
images/
|
||||||
|
|
||||||
|
docs/
|
||||||
|
|
||||||
|
# Virtualenv
|
||||||
|
.env/
|
||||||
|
virtual/
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
70
conf.py
70
conf.py
|
@ -26,7 +26,7 @@ import logging
|
||||||
TYPE_EXTENSION = 1
|
TYPE_EXTENSION = 1
|
||||||
|
|
||||||
# ~ https://semver.org/
|
# ~ https://semver.org/
|
||||||
VERSION = '0.1.0'
|
VERSION = '0.2.0'
|
||||||
|
|
||||||
# ~ Your great extension name, not used spaces
|
# ~ Your great extension name, not used spaces
|
||||||
NAME = 'ZAZBarCode'
|
NAME = 'ZAZBarCode'
|
||||||
|
@ -34,6 +34,9 @@ NAME = 'ZAZBarCode'
|
||||||
# ~ Should be unique, used URL inverse
|
# ~ Should be unique, used URL inverse
|
||||||
ID = 'net.elmau.zaz.BarCode'
|
ID = 'net.elmau.zaz.BarCode'
|
||||||
|
|
||||||
|
# ~ If you extension will be multilanguage set True
|
||||||
|
USE_LOCALES = False
|
||||||
|
|
||||||
PUBLISHER = {
|
PUBLISHER = {
|
||||||
'en': {'text': 'El Mau', 'link': 'https://gitlab.com/mauriciobaeza'},
|
'en': {'text': 'El Mau', 'link': 'https://gitlab.com/mauriciobaeza'},
|
||||||
'es': {'text': 'El Mau', 'link': 'https://gitlab.com/mauriciobaeza'},
|
'es': {'text': 'El Mau', 'link': 'https://gitlab.com/mauriciobaeza'},
|
||||||
|
@ -66,7 +69,6 @@ LICENSE_EN = f"""This file is part of {NAME}.
|
||||||
"""
|
"""
|
||||||
LICENSE_ES = LICENSE_EN
|
LICENSE_ES = LICENSE_EN
|
||||||
|
|
||||||
|
|
||||||
INFO = {
|
INFO = {
|
||||||
'en': {
|
'en': {
|
||||||
'display_name': 'ZAZ Bar Code',
|
'display_name': 'ZAZ Bar Code',
|
||||||
|
@ -258,6 +260,7 @@ DIRS = {
|
||||||
'registration': 'registration',
|
'registration': 'registration',
|
||||||
'files': 'files',
|
'files': 'files',
|
||||||
'pythonpath': False,
|
'pythonpath': False,
|
||||||
|
'locales': 'locales',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -279,16 +282,21 @@ FILES = {
|
||||||
|
|
||||||
# ~ URLs for update for example
|
# ~ URLs for update for example
|
||||||
# ~ URL_XML_UPDATE = 'https://gitlab.com/USER/PROYECT/raw/BRANCH/FOLDERs/FILE_NAME'
|
# ~ URL_XML_UPDATE = 'https://gitlab.com/USER/PROYECT/raw/BRANCH/FOLDERs/FILE_NAME'
|
||||||
URL_XML_UPDATE = ''
|
URL_BASE = 'https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/'
|
||||||
URL_OXT = ''
|
URL_XML_UPDATE = URL_BASE + FILES['update']
|
||||||
|
URL_OXT = URL_BASE + FILES['oxt']
|
||||||
|
|
||||||
|
|
||||||
FILE_TEST = '/home/mau/test/test.ods'
|
# ~ Default program for test: --calc, --writer, --draw
|
||||||
|
PROGRAM = '--calc'
|
||||||
|
# ~ Path to file for test
|
||||||
|
FILE_TEST = ''
|
||||||
|
|
||||||
PATHS = {
|
PATHS = {
|
||||||
'idlc': '/usr/lib/libreoffice/sdk/bin/idlc',
|
'idlc': '/usr/lib/libreoffice/sdk/bin/idlc',
|
||||||
'include': '/usr/share/idl/libreoffice',
|
'include': '/usr/share/idl/libreoffice',
|
||||||
'regmerge': '/usr/lib/libreoffice/program/regmerge',
|
'regmerge': '/usr/lib/libreoffice/program/regmerge',
|
||||||
'soffice': ('soffice', '--calc', FILE_TEST),
|
'soffice': ('soffice', PROGRAM, FILE_TEST),
|
||||||
'install': ('unopkg', 'add', '-v', '-f', '-s'),
|
'install': ('unopkg', 'add', '-v', '-f', '-s'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +453,8 @@ if PARENT == 'OfficeMenuBar':
|
||||||
|
|
||||||
|
|
||||||
def _get_context(args):
|
def _get_context(args):
|
||||||
|
if not args:
|
||||||
|
return ''
|
||||||
c = []
|
c = []
|
||||||
for v in args.split(','):
|
for v in args.split(','):
|
||||||
c.append(CONTEXT[v])
|
c.append(CONTEXT[v])
|
||||||
|
@ -472,29 +482,31 @@ for i, m in enumerate(MENUS):
|
||||||
toolbar.append(NODE_MENU.format(**values))
|
toolbar.append(NODE_MENU.format(**values))
|
||||||
|
|
||||||
NODE_TOOLBAR = ''
|
NODE_TOOLBAR = ''
|
||||||
if PARENT == 'AddonMenu':
|
NODE_MENUS = ''
|
||||||
NODE_MENUS = '\n'.join(menus)
|
if TYPE_EXTENSION == 1:
|
||||||
else:
|
if PARENT == 'AddonMenu':
|
||||||
tmp = ' <value xml:lang="{}">{}</value>'
|
NODE_MENUS = '\n'.join(menus)
|
||||||
titles = '\n'.join([tmp.format(k, v) for k, v in MENU_MAIN.items()])
|
else:
|
||||||
SUBMENUS = '<node oor:name="Submenu">\n ' + '\n'.join(menus) + '\n </node>'
|
tmp = ' <value xml:lang="{}">{}</value>'
|
||||||
NODE_MENUS = f""" <node oor:name="{ID}" oor:op="replace">
|
titles = '\n'.join([tmp.format(k, v) for k, v in MENU_MAIN.items()])
|
||||||
<prop oor:name="Title" oor:type="xs:string">
|
SUBMENUS = '<node oor:name="Submenu">\n ' + '\n'.join(menus) + '\n </node>'
|
||||||
{titles}
|
NODE_MENUS = f""" <node oor:name="{ID}" oor:op="replace">
|
||||||
</prop>
|
<prop oor:name="Title" oor:type="xs:string">
|
||||||
<prop oor:name="Target" oor:type="xs:string">
|
{titles}
|
||||||
<value>_self</value>
|
</prop>
|
||||||
</prop>
|
<prop oor:name="Target" oor:type="xs:string">
|
||||||
{SUBMENUS}
|
<value>_self</value>
|
||||||
</node>"""
|
</prop>
|
||||||
|
{SUBMENUS}
|
||||||
|
</node>"""
|
||||||
|
|
||||||
if toolbar:
|
if toolbar:
|
||||||
node_toolbars = '\n'.join(toolbar)
|
node_toolbars = '\n'.join(toolbar)
|
||||||
NODE_TOOLBAR = f""" <node oor:name="OfficeToolBar">
|
NODE_TOOLBAR = f""" <node oor:name="OfficeToolBar">
|
||||||
<node oor:name="{ID}" oor:op="replace">
|
<node oor:name="{ID}" oor:op="replace">
|
||||||
{node_toolbars}
|
{node_toolbars}
|
||||||
</node>
|
</node>
|
||||||
</node>"""
|
</node>"""
|
||||||
|
|
||||||
FILE_ADDONS = f"""<?xml version='1.0' encoding='UTF-8'?>
|
FILE_ADDONS = f"""<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Addons" oor:package="org.openoffice.Office">
|
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Addons" oor:package="org.openoffice.Office">
|
||||||
|
@ -668,5 +680,5 @@ DATA = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# ~ LICENSE_ACCEPT_BY = 'admin' # or admin
|
# ~ LICENSE_ACCEPT_BY = 'user' # or admin
|
||||||
# ~ LICENSE_SUPPRESS_ON_UPDATE = True
|
# ~ LICENSE_SUPPRESS_ON_UPDATE = True
|
||||||
|
|
540
easymacro.py
540
easymacro.py
|
@ -18,15 +18,26 @@
|
||||||
# ~ along with ZAZ. If not, see <https://www.gnu.org/licenses/>.
|
# ~ along with ZAZ. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import datetime
|
||||||
|
import errno
|
||||||
import getpass
|
import getpass
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from pathlib import Path, PurePath
|
||||||
|
from pprint import pprint
|
||||||
|
from subprocess import PIPE
|
||||||
|
|
||||||
import uno
|
import uno
|
||||||
import unohelper
|
import unohelper
|
||||||
|
@ -35,6 +46,7 @@ from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS
|
||||||
from com.sun.star.awt.MessageBoxResults import YES
|
from com.sun.star.awt.MessageBoxResults import YES
|
||||||
from com.sun.star.awt.PosSize import POSSIZE, SIZE
|
from com.sun.star.awt.PosSize import POSSIZE, SIZE
|
||||||
from com.sun.star.awt import Size, Point
|
from com.sun.star.awt import Size, Point
|
||||||
|
from com.sun.star.datatransfer import XTransferable, DataFlavor
|
||||||
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
|
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
|
||||||
|
|
||||||
from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
|
from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
|
||||||
|
@ -44,31 +56,46 @@ from com.sun.star.awt import XActionListener
|
||||||
from com.sun.star.awt import XMouseListener
|
from com.sun.star.awt import XMouseListener
|
||||||
|
|
||||||
|
|
||||||
FILE_NAME_DEBUG = 'debug.log'
|
|
||||||
MSG_LANG = {
|
MSG_LANG = {
|
||||||
'es': {
|
'es': {
|
||||||
'OK': 'Aceptar',
|
'OK': 'Aceptar',
|
||||||
'Cancel': 'Cancelar',
|
'Cancel': 'Cancelar',
|
||||||
|
'Select file': 'Seleccionar archivo',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
|
||||||
DATE = '%d/%m/%Y %H:%M:%S'
|
FILE_NAME_DEBUG = 'zaz-debug.log'
|
||||||
|
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||||
|
LOG_DATE = '%d/%m/%Y %H:%M:%S'
|
||||||
LEVEL_ERROR = logging.getLevelName(logging.ERROR)
|
LEVEL_ERROR = logging.getLevelName(logging.ERROR)
|
||||||
LEVEL_DEBUG = logging.getLevelName(logging.DEBUG)
|
LEVEL_DEBUG = logging.getLevelName(logging.DEBUG)
|
||||||
LEVEL_INFO = logging.getLevelName(logging.INFO)
|
LEVEL_INFO = logging.getLevelName(logging.INFO)
|
||||||
logging.addLevelName(logging.ERROR, f'\033[1;41m{LEVEL_ERROR}\033[1;0m')
|
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.DEBUG, f'\x1b[33m{LEVEL_DEBUG}\033[1;0m')
|
||||||
logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m')
|
logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m')
|
||||||
logging.basicConfig(level=logging.DEBUG, format=FORMAT, datefmt=DATE)
|
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
OS = platform.system()
|
||||||
|
USER = getpass.getuser()
|
||||||
|
PC = platform.node()
|
||||||
|
DESKTOP = os.environ.get('DESKTOP_SESSION', '')
|
||||||
|
INFO_DEBUG = '{}\n\n{}\n\n{}'.format(sys.version, platform.platform(), '\n'.join(sys.path))
|
||||||
|
|
||||||
|
IS_WIN = OS == 'Windows'
|
||||||
|
LOG_NAME = 'ZAZ'
|
||||||
|
CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16'
|
||||||
|
|
||||||
|
CALC = 'calc'
|
||||||
|
WRITER = 'writer'
|
||||||
OBJ_CELL = 'ScCellObj'
|
OBJ_CELL = 'ScCellObj'
|
||||||
OBJ_RANGE = 'ScCellRangeObj'
|
OBJ_RANGE = 'ScCellRangeObj'
|
||||||
OBJ_RANGES = 'ScCellRangesObj'
|
OBJ_RANGES = 'ScCellRangesObj'
|
||||||
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
|
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
|
||||||
|
|
||||||
|
|
||||||
CTX = uno.getComponentContext()
|
CTX = uno.getComponentContext()
|
||||||
SM = CTX.getServiceManager()
|
SM = CTX.getServiceManager()
|
||||||
|
|
||||||
|
@ -96,17 +123,10 @@ def _get_config(key, node_name):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
OS = sys.platform
|
|
||||||
USER = getpass.getuser()
|
|
||||||
PC = platform.node()
|
|
||||||
|
|
||||||
LANGUAGE = _get_config('ooLocale', 'org.openoffice.Setup/L10N/')
|
LANGUAGE = _get_config('ooLocale', 'org.openoffice.Setup/L10N/')
|
||||||
|
LANG = LANGUAGE.split('-')[0]
|
||||||
NAME = TITLE = _get_config('ooName', 'org.openoffice.Setup/Product')
|
NAME = TITLE = _get_config('ooName', 'org.openoffice.Setup/Product')
|
||||||
VERSION = _get_config('ooSetupVersion', '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):
|
def mri(obj):
|
||||||
|
@ -120,7 +140,45 @@ def mri(obj):
|
||||||
return
|
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
|
||||||
|
|
||||||
|
|
||||||
|
class LogWin(object):
|
||||||
|
|
||||||
|
def __init__(self, doc):
|
||||||
|
self.doc = doc
|
||||||
|
|
||||||
|
def write(self, info):
|
||||||
|
text = self.doc.Text
|
||||||
|
cursor = text.createTextCursor()
|
||||||
|
cursor.gotoEnd(False)
|
||||||
|
text.insertString(cursor, str(info), 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def info(data):
|
||||||
|
log.info(data)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def debug(info):
|
def debug(info):
|
||||||
|
if IS_WIN:
|
||||||
|
# ~ app = LOApp(self.ctx, self.sm, self.desktop, self.toolkit)
|
||||||
|
# ~ doc = app.getDoc(FILE_NAME_DEBUG)
|
||||||
|
# ~ if not doc:
|
||||||
|
# ~ doc = app.newDoc(WRITER)
|
||||||
|
# ~ out = OutputDoc(doc)
|
||||||
|
# ~ sys.stdout = out
|
||||||
|
pprint(info)
|
||||||
|
return
|
||||||
|
|
||||||
log.debug(info)
|
log.debug(info)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -130,14 +188,11 @@ def error(info):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def catch_exception(f):
|
def save_log(path, data):
|
||||||
@wraps(f)
|
with open(path, 'a') as out:
|
||||||
def func(*args, **kwargs):
|
out.write('{} -{}- '.format(str(datetime.now())[:19], LOG_NAME))
|
||||||
try:
|
pprint(data, stream=out)
|
||||||
return f(*args, **kwargs)
|
return
|
||||||
except Exception as e:
|
|
||||||
log.error(f.__name__, exc_info=True)
|
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
def run_in_thread(fn):
|
def run_in_thread(fn):
|
||||||
|
@ -187,6 +242,10 @@ def get_desktop():
|
||||||
return create_instance('com.sun.star.frame.Desktop', True)
|
return create_instance('com.sun.star.frame.Desktop', True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_dispatch():
|
||||||
|
return create_instance('com.sun.star.frame.DispatchHelper')
|
||||||
|
|
||||||
|
|
||||||
def get_temp_file():
|
def get_temp_file():
|
||||||
return tempfile.NamedTemporaryFile()
|
return tempfile.NamedTemporaryFile()
|
||||||
|
|
||||||
|
@ -203,6 +262,20 @@ def _path_system(path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def exists_app(name):
|
||||||
|
try:
|
||||||
|
dn = subprocess.DEVNULL
|
||||||
|
subprocess.Popen([name, ''], stdout=dn, stderr=dn).terminate()
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.ENOENT:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def exists(path):
|
||||||
|
return Path(path).exists()
|
||||||
|
|
||||||
|
|
||||||
def get_type_doc(obj):
|
def get_type_doc(obj):
|
||||||
services = {
|
services = {
|
||||||
'calc': 'com.sun.star.sheet.SpreadsheetDocument',
|
'calc': 'com.sun.star.sheet.SpreadsheetDocument',
|
||||||
|
@ -219,6 +292,11 @@ def get_type_doc(obj):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def _properties(values):
|
||||||
|
p = [PropertyValue(Name=n, Value=v) for n, v in values.items()]
|
||||||
|
return tuple(p)
|
||||||
|
|
||||||
|
|
||||||
# ~ Custom classes
|
# ~ Custom classes
|
||||||
|
|
||||||
|
|
||||||
|
@ -245,6 +323,10 @@ class LODocument(object):
|
||||||
def title(self):
|
def title(self):
|
||||||
return self.obj.getTitle()
|
return self.obj.getTitle()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def frame(self):
|
||||||
|
return self._cc.getFrame()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_saved(self):
|
def is_saved(self):
|
||||||
return self.obj.hasLocation()
|
return self.obj.hasLocation()
|
||||||
|
@ -281,6 +363,29 @@ class LODocument(object):
|
||||||
obj = self.obj.createInstance(name)
|
obj = self.obj.createInstance(name)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
def save(self, path='', **kwargs):
|
||||||
|
opt = _properties(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()
|
||||||
|
|
||||||
|
|
||||||
class LOCalc(LODocument):
|
class LOCalc(LODocument):
|
||||||
|
|
||||||
|
@ -313,9 +418,14 @@ class LOCalc(LODocument):
|
||||||
cell = LOCellRange(self.active[index].obj, self)
|
cell = LOCellRange(self.active[index].obj, self)
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
# ~ def create_instance(self, name):
|
def select(self, rango):
|
||||||
# ~ obj = self.obj.createInstance(name)
|
r = rango
|
||||||
# ~ return obj
|
if hasattr(rango, 'obj'):
|
||||||
|
r = rango.obj
|
||||||
|
elif isinstance(rango, str):
|
||||||
|
r = self.get_cell(rango).obj
|
||||||
|
self._cc.select(r)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class LOCalcSheet(object):
|
class LOCalcSheet(object):
|
||||||
|
@ -464,6 +574,11 @@ class LOBasicIde(LODocument):
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
super().__init__(obj)
|
super().__init__(obj)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def selection(self):
|
||||||
|
sel = self._cc.getSelection()
|
||||||
|
return sel
|
||||||
|
|
||||||
|
|
||||||
class LOCellRange(object):
|
class LOCellRange(object):
|
||||||
|
|
||||||
|
@ -587,6 +702,10 @@ class LOCellRange(object):
|
||||||
img.setSize(Size(w, h))
|
img.setSize(Size(w, h))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def select(self):
|
||||||
|
self.doc._cc.select(self.obj)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class EventsListenerBase(unohelper.Base, XEventListener):
|
class EventsListenerBase(unohelper.Base, XEventListener):
|
||||||
|
|
||||||
|
@ -926,6 +1045,7 @@ class LODialog(object):
|
||||||
}
|
}
|
||||||
return classes[tipo](obj)
|
return classes[tipo](obj)
|
||||||
|
|
||||||
|
@catch_exception
|
||||||
def add_control(self, properties):
|
def add_control(self, properties):
|
||||||
tipo = properties.pop('Type').lower()
|
tipo = properties.pop('Type').lower()
|
||||||
model = self.model.createInstance(self._get_control_model(tipo))
|
model = self.model.createInstance(self._get_control_model(tipo))
|
||||||
|
@ -998,3 +1118,377 @@ def set_properties(model, properties):
|
||||||
values = tuple(properties.values())
|
values = tuple(properties.values())
|
||||||
model.setPropertyValues(keys, values)
|
model.setPropertyValues(keys, values)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def get_file(filters=(), multiple=False):
|
||||||
|
file_picker = create_instance('com.sun.star.ui.dialogs.FilePicker')
|
||||||
|
file_picker.setTitle(_('Select file'))
|
||||||
|
file_picker.setMultiSelectionMode(multiple)
|
||||||
|
|
||||||
|
if filters:
|
||||||
|
file_picker.setCurrentFilter(filters[0][0])
|
||||||
|
for f in filters:
|
||||||
|
file_picker.appendFilter(f[0], f[1])
|
||||||
|
|
||||||
|
if file_picker.execute():
|
||||||
|
if multiple:
|
||||||
|
return [_path_system(f) for f in file_picker.getSelectedFiles()]
|
||||||
|
return _path_system(file_picker.getSelectedFiles()[0])
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def get_info_path(path):
|
||||||
|
path, filename = os.path.split(path)
|
||||||
|
name, extension = os.path.splitext(filename)
|
||||||
|
return (path, filename, name, extension)
|
||||||
|
|
||||||
|
|
||||||
|
def inputbox(message, default='', title=TITLE):
|
||||||
|
|
||||||
|
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(dlg)
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
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 new_doc(type_doc=CALC):
|
||||||
|
path = 'private:factory/s{}'.format(type_doc)
|
||||||
|
doc = get_desktop().loadComponentFromURL(path, '_default', 0, ())
|
||||||
|
return _get_class_doc(doc)
|
||||||
|
|
||||||
|
|
||||||
|
def open_doc(path, **kwargs):
|
||||||
|
""" Open document in path
|
||||||
|
Usually options:
|
||||||
|
Hidden: True or False
|
||||||
|
AsTemplate: True or False
|
||||||
|
ReadOnly: True or False
|
||||||
|
Password: super_secret
|
||||||
|
MacroExecutionMode: 4 = Activate macros
|
||||||
|
Preview: True or False
|
||||||
|
|
||||||
|
http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1frame_1_1XComponentLoader.html
|
||||||
|
http://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1document_1_1MediaDescriptor.html
|
||||||
|
"""
|
||||||
|
path = _path_url(path)
|
||||||
|
opt = _properties(kwargs)
|
||||||
|
doc = get_desktop().loadComponentFromURL(path, '_blank', 0, opt)
|
||||||
|
if doc is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
return _get_class_doc(doc)
|
||||||
|
|
||||||
|
|
||||||
|
def open_file(path):
|
||||||
|
if IS_WIN:
|
||||||
|
os.startfile(path)
|
||||||
|
else:
|
||||||
|
subprocess.Popen(['xdg-open', path])
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def join(*paths):
|
||||||
|
return os.path.join(*paths)
|
||||||
|
|
||||||
|
|
||||||
|
def is_dir(path):
|
||||||
|
return Path(path).is_dir()
|
||||||
|
|
||||||
|
|
||||||
|
def is_file(path):
|
||||||
|
return Path(path).is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_size(path):
|
||||||
|
return Path(path).stat().st_size
|
||||||
|
|
||||||
|
|
||||||
|
def is_created(path):
|
||||||
|
return is_file(path) and bool(get_file_size(path))
|
||||||
|
|
||||||
|
|
||||||
|
def replace_ext(path, ext):
|
||||||
|
path, _, name, _ = get_info_path(path)
|
||||||
|
return '{}/{}.{}'.format(path, name, ext)
|
||||||
|
|
||||||
|
|
||||||
|
def zip_names(path):
|
||||||
|
with zipfile.ZipFile(path) as z:
|
||||||
|
names = z.namelist()
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
def run(command, wait=False):
|
||||||
|
# ~ debug(command)
|
||||||
|
# ~ debug(shlex.split(command))
|
||||||
|
try:
|
||||||
|
if wait:
|
||||||
|
# ~ p = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
|
||||||
|
# ~ p.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 = ("run [ERROR]: output = %s, error code = %s\n"
|
||||||
|
% (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)
|
||||||
|
|
||||||
|
|
||||||
|
def zip(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)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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 kill(path):
|
||||||
|
p = Path(path)
|
||||||
|
if p.is_file():
|
||||||
|
try:
|
||||||
|
p.unlink()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif p.is_dir():
|
||||||
|
p.rmdir()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
def get_clipboard():
|
||||||
|
df = None
|
||||||
|
text = ''
|
||||||
|
sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard')
|
||||||
|
transferable = sc.getContents()
|
||||||
|
data = transferable.getTransferDataFlavors()
|
||||||
|
for df in data:
|
||||||
|
if df.MimeType == CLIPBOARD_FORMAT_TEXT:
|
||||||
|
break
|
||||||
|
if df:
|
||||||
|
text = transferable.getTransferData(df)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
class TextTransferable(unohelper.Base, XTransferable):
|
||||||
|
"""Keep clipboard data and provide them."""
|
||||||
|
|
||||||
|
def __init__(self, text):
|
||||||
|
df = DataFlavor()
|
||||||
|
df.MimeType = CLIPBOARD_FORMAT_TEXT
|
||||||
|
df.HumanPresentableName = "encoded text utf-16"
|
||||||
|
self.flavors = [df]
|
||||||
|
self.data = [text]
|
||||||
|
|
||||||
|
def getTransferData(self, flavor):
|
||||||
|
if not flavor:
|
||||||
|
return
|
||||||
|
for i, f in enumerate(self.flavors):
|
||||||
|
if flavor.MimeType == f.MimeType:
|
||||||
|
return self.data[i]
|
||||||
|
return
|
||||||
|
|
||||||
|
def getTransferDataFlavors(self):
|
||||||
|
return tuple(self.flavors)
|
||||||
|
|
||||||
|
def isDataFlavorSupported(self, flavor):
|
||||||
|
if not flavor:
|
||||||
|
return False
|
||||||
|
mtype = flavor.MimeType
|
||||||
|
for f in self.flavors:
|
||||||
|
if mtype == f.MimeType:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def set_clipboard(text):
|
||||||
|
ts = TextTransferable(text)
|
||||||
|
sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard')
|
||||||
|
sc.setContents(ts, None)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def copy(doc=None):
|
||||||
|
if doc is None:
|
||||||
|
doc = get_document()
|
||||||
|
if hasattr(doc, 'frame'):
|
||||||
|
frame = doc.frame
|
||||||
|
else:
|
||||||
|
frame = doc.getCurrentController().getFrame()
|
||||||
|
dispatch = get_dispatch()
|
||||||
|
dispatch.executeDispatch(frame, '.uno:Copy', '', 0, ())
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def get_epoch():
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
return int(time.mktime(now.timetuple()))
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<description
|
||||||
|
xmlns="http://openoffice.org/extensions/update/2006"
|
||||||
|
xmlns:d="http://openoffice.org/extensions/description/2006"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
|
||||||
|
<identifier value="net.elmau.zaz.BarCode" />
|
||||||
|
<version value="0.2.0" />
|
||||||
|
|
||||||
|
<update-download>
|
||||||
|
<src xlink:href="https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/ZAZBarCode_v0.2.0.oxt"/>
|
||||||
|
</update-download>
|
||||||
|
<release-notes>
|
||||||
|
</release-notes>
|
||||||
|
|
||||||
|
</description>
|
|
@ -3,14 +3,14 @@
|
||||||
<node oor:name="AddonUI">
|
<node oor:name="AddonUI">
|
||||||
<node oor:name="OfficeMenuBar">
|
<node oor:name="OfficeMenuBar">
|
||||||
<node oor:name="net.elmau.zaz.BarCode" oor:op="replace">
|
<node oor:name="net.elmau.zaz.BarCode" oor:op="replace">
|
||||||
<prop oor:name="Title" oor:type="xs:string">
|
<prop oor:name="Title" oor:type="xs:string">
|
||||||
<value xml:lang="en">ZAZ BarCode</value>
|
<value xml:lang="en">ZAZ BarCode</value>
|
||||||
<value xml:lang="es">ZAZ BarCode</value>
|
<value xml:lang="es">ZAZ BarCode</value>
|
||||||
</prop>
|
</prop>
|
||||||
<prop oor:name="Target" oor:type="xs:string">
|
<prop oor:name="Target" oor:type="xs:string">
|
||||||
<value>_self</value>
|
<value>_self</value>
|
||||||
</prop>
|
</prop>
|
||||||
<node oor:name="Submenu">
|
<node oor:name="Submenu">
|
||||||
<node oor:name="net.elmau.zaz.BarCode.101" oor:op="replace">
|
<node oor:name="net.elmau.zaz.BarCode.101" oor:op="replace">
|
||||||
<prop oor:name="Title" oor:type="xs:string">
|
<prop oor:name="Title" oor:type="xs:string">
|
||||||
<value xml:lang="en">Insert BarCode</value>
|
<value xml:lang="en">Insert BarCode</value>
|
||||||
|
@ -318,7 +318,7 @@
|
||||||
</prop>
|
</prop>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
||||||
</node>
|
</node>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
import gettext
|
||||||
import uno
|
import uno
|
||||||
import unohelper
|
import unohelper
|
||||||
from com.sun.star.task import XJobExecutor
|
from com.sun.star.task import XJobExecutor
|
||||||
|
import easymacro as app
|
||||||
|
|
||||||
import qrcode
|
import qrcode
|
||||||
import qrcode.image.svg as svg
|
import qrcode.image.svg as svg
|
||||||
from barcode import generate
|
from barcode import generate
|
||||||
|
|
||||||
import easymacro as app
|
|
||||||
|
|
||||||
|
|
||||||
ID_EXTENSION = 'net.elmau.zaz.BarCode'
|
ID_EXTENSION = 'net.elmau.zaz.BarCode'
|
||||||
SERVICE = ('com.sun.star.task.Job',)
|
SERVICE = ('com.sun.star.task.Job',)
|
||||||
|
@ -15,20 +15,31 @@ TITLE = 'ZAZ BarCode'
|
||||||
QR = 'qrcode'
|
QR = 'qrcode'
|
||||||
|
|
||||||
|
|
||||||
|
p, *_ = app.get_info_path(__file__)
|
||||||
|
path_locales = app.join(p, 'locales')
|
||||||
|
try:
|
||||||
|
lang = gettext.translation('base', path_locales, languages=[app.LANG])
|
||||||
|
lang.install()
|
||||||
|
_ = lang.gettext
|
||||||
|
except Exception as e:
|
||||||
|
app.error(e)
|
||||||
|
|
||||||
|
|
||||||
class Controllers(object):
|
class Controllers(object):
|
||||||
|
|
||||||
|
@app.catch_exception
|
||||||
def __init__(self, dlg):
|
def __init__(self, dlg):
|
||||||
self.d = dlg
|
self.d = dlg
|
||||||
|
|
||||||
def button_action(self, event):
|
def button_action(self, event):
|
||||||
if not self.d.listbox.value:
|
if not self.d.listbox.value:
|
||||||
self.d.listbox.set_focus()
|
self.d.listbox.set_focus()
|
||||||
msg = 'Select barcode type'
|
msg = _('Select barcode type')
|
||||||
app.warning(msg, TITLE)
|
app.warning(msg, TITLE)
|
||||||
return
|
return
|
||||||
if not self.d.text.value.strip():
|
if not self.d.text.value.strip():
|
||||||
self.d.text.set_focus()
|
self.d.text.set_focus()
|
||||||
msg = 'Data field is mandatory'
|
msg = _('Data field is mandatory')
|
||||||
app.warning(msg, TITLE)
|
app.warning(msg, TITLE)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -43,6 +54,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
self._data = ''
|
self._data = ''
|
||||||
self._type = ''
|
self._type = ''
|
||||||
|
|
||||||
|
@app.catch_exception
|
||||||
def trigger(self, args):
|
def trigger(self, args):
|
||||||
self._type = args
|
self._type = args
|
||||||
if args == 'ask' and not self._get_values():
|
if args == 'ask' and not self._get_values():
|
||||||
|
@ -79,7 +91,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
if not self._data:
|
if not self._data:
|
||||||
self._data = cell.value
|
self._data = cell.value
|
||||||
if not self._data:
|
if not self._data:
|
||||||
msg = 'Select data'
|
msg = _('Select data')
|
||||||
self._show_error(msg)
|
self._show_error(msg)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -101,7 +113,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
if not self._data:
|
if not self._data:
|
||||||
self._data = sel.string
|
self._data = sel.string
|
||||||
if not self._data:
|
if not self._data:
|
||||||
msg = 'Select data'
|
msg = _('Select data')
|
||||||
self._show_error(msg)
|
self._show_error(msg)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -133,7 +145,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
return
|
return
|
||||||
|
|
||||||
def _show_error(self, error):
|
def _show_error(self, error):
|
||||||
msg = 'Error in: {}\n\n{}'.format(self._type, error)
|
msg = _('Error in: {}\n\n{}').format(self._type, error)
|
||||||
app.error(error)
|
app.error(error)
|
||||||
app.errorbox(msg, TITLE)
|
app.errorbox(msg, TITLE)
|
||||||
return
|
return
|
||||||
|
@ -151,12 +163,11 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
args = {
|
args = {
|
||||||
'Type': 'Label',
|
'Type': 'Label',
|
||||||
'Name': 'lbl_barcode',
|
'Name': 'lbl_barcode',
|
||||||
'Label': 'Select barcode type',
|
'Label': _('~Select barcode type'),
|
||||||
'Width': 55,
|
'Width': 70,
|
||||||
'Height': 15,
|
'Height': 15,
|
||||||
'X': 10,
|
'X': 10,
|
||||||
'Y': 10,
|
'Y': 10,
|
||||||
'Align': 2,
|
|
||||||
'VerticalAlign': 1,
|
'VerticalAlign': 1,
|
||||||
}
|
}
|
||||||
dlg.add_control(args)
|
dlg.add_control(args)
|
||||||
|
@ -164,8 +175,8 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
args = {
|
args = {
|
||||||
'Type': 'Label',
|
'Type': 'Label',
|
||||||
'Name': 'lbl_data',
|
'Name': 'lbl_data',
|
||||||
'Label': 'Capture data for barcode',
|
'Label': _('~Capture data for barcode'),
|
||||||
'Width': 70,
|
'Width': 100,
|
||||||
'Height': 15,
|
'Height': 15,
|
||||||
'VerticalAlign': 1,
|
'VerticalAlign': 1,
|
||||||
}
|
}
|
||||||
|
@ -174,7 +185,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
args = {
|
args = {
|
||||||
'Type': 'ListBox',
|
'Type': 'ListBox',
|
||||||
'Name': 'listbox',
|
'Name': 'listbox',
|
||||||
'Width': 80,
|
'Width': 65,
|
||||||
'Height': 15,
|
'Height': 15,
|
||||||
'Dropdown': True,
|
'Dropdown': True,
|
||||||
}
|
}
|
||||||
|
@ -197,7 +208,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
|
||||||
args = {
|
args = {
|
||||||
'Type': 'Button',
|
'Type': 'Button',
|
||||||
'Name': 'button',
|
'Name': 'button',
|
||||||
'Label': 'Insert Barcode',
|
'Label': _('~Insert Barcode'),
|
||||||
'Width': 60,
|
'Width': 60,
|
||||||
'Height': 15,
|
'Height': 15,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:d="http://openoffice.org/extensions/description/2006">
|
<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:d="http://openoffice.org/extensions/description/2006">
|
||||||
<identifier value="net.elmau.zaz.BarCode" />
|
<identifier value="net.elmau.zaz.BarCode" />
|
||||||
<version value="0.1.0" />
|
<version value="0.2.0" />
|
||||||
<display-name>
|
<display-name>
|
||||||
<name lang="en">ZAZ Bar Code</name>
|
<name lang="en">ZAZ Bar Code</name>
|
||||||
<name lang="es">ZAZ Códigos de Barras</name>
|
<name lang="es">ZAZ Códigos de Barras</name>
|
||||||
|
@ -23,4 +23,7 @@
|
||||||
<license-text xlink:href="registration/license_es.txt" lang="es" />
|
<license-text xlink:href="registration/license_es.txt" lang="es" />
|
||||||
</simple-license>
|
</simple-license>
|
||||||
</registration>
|
</registration>
|
||||||
|
<update-information>
|
||||||
|
<src xlink:href="https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/zazbarcode.update.xml" />
|
||||||
|
</update-information>
|
||||||
</description>
|
</description>
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ORGANIZATION
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"POT-Creation-Date: 2019-09-14 14:23-0500\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:38
|
||||||
|
msgid "Select barcode type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:43
|
||||||
|
msgid "Data field is mandatory"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:95 source/ZAZBarCode.py:117
|
||||||
|
msgid "Select data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:149
|
||||||
|
msgid ""
|
||||||
|
"Error in: {}\n"
|
||||||
|
"\n"
|
||||||
|
"{}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:167
|
||||||
|
msgid "~Select barcode type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:179
|
||||||
|
msgid "~Capture data for barcode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:212
|
||||||
|
msgid "~Insert Barcode"
|
||||||
|
msgstr ""
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,49 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ORGANIZATION
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"POT-Creation-Date: 2019-09-14 14:23-0500\n"
|
||||||
|
"PO-Revision-Date: 2019-09-14 14:45-0500\n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
"X-Generator: Poedit 2.2.1\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"Language: en\n"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:38
|
||||||
|
msgid "Select barcode type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:43
|
||||||
|
msgid "Data field is mandatory"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:95 source/ZAZBarCode.py:117
|
||||||
|
msgid "Select data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:149
|
||||||
|
msgid ""
|
||||||
|
"Error in: {}\n"
|
||||||
|
"\n"
|
||||||
|
"{}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:167
|
||||||
|
msgid "~Select barcode type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:179
|
||||||
|
msgid "~Capture data for barcode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:212
|
||||||
|
msgid "~Insert Barcode"
|
||||||
|
msgstr ""
|
Binary file not shown.
|
@ -0,0 +1,52 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ORGANIZATION
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"POT-Creation-Date: 2019-09-14 14:23-0500\n"
|
||||||
|
"PO-Revision-Date: 2019-09-14 14:44-0500\n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
"X-Generator: Poedit 2.2.1\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"Language: es\n"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:38
|
||||||
|
msgid "Select barcode type"
|
||||||
|
msgstr "Seleccione el tipo de código de barras"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:43
|
||||||
|
msgid "Data field is mandatory"
|
||||||
|
msgstr "Los datos son obligatorios"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:95 source/ZAZBarCode.py:117
|
||||||
|
msgid "Select data"
|
||||||
|
msgstr "Seleccione los datos"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:149
|
||||||
|
msgid ""
|
||||||
|
"Error in: {}\n"
|
||||||
|
"\n"
|
||||||
|
"{}"
|
||||||
|
msgstr ""
|
||||||
|
"Error en: {}\n"
|
||||||
|
"\n"
|
||||||
|
"{}"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:167
|
||||||
|
msgid "~Select barcode type"
|
||||||
|
msgstr "~Tipo de código de barras"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:179
|
||||||
|
msgid "~Capture data for barcode"
|
||||||
|
msgstr "~Datos del código de barras"
|
||||||
|
|
||||||
|
#: source/ZAZBarCode.py:212
|
||||||
|
msgid "~Insert Barcode"
|
||||||
|
msgstr "~Insertar Código"
|
|
@ -18,15 +18,26 @@
|
||||||
# ~ along with ZAZ. If not, see <https://www.gnu.org/licenses/>.
|
# ~ along with ZAZ. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import datetime
|
||||||
|
import errno
|
||||||
import getpass
|
import getpass
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from pathlib import Path, PurePath
|
||||||
|
from pprint import pprint
|
||||||
|
from subprocess import PIPE
|
||||||
|
|
||||||
import uno
|
import uno
|
||||||
import unohelper
|
import unohelper
|
||||||
|
@ -35,6 +46,7 @@ from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS
|
||||||
from com.sun.star.awt.MessageBoxResults import YES
|
from com.sun.star.awt.MessageBoxResults import YES
|
||||||
from com.sun.star.awt.PosSize import POSSIZE, SIZE
|
from com.sun.star.awt.PosSize import POSSIZE, SIZE
|
||||||
from com.sun.star.awt import Size, Point
|
from com.sun.star.awt import Size, Point
|
||||||
|
from com.sun.star.datatransfer import XTransferable, DataFlavor
|
||||||
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
|
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
|
||||||
|
|
||||||
from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
|
from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
|
||||||
|
@ -44,31 +56,46 @@ from com.sun.star.awt import XActionListener
|
||||||
from com.sun.star.awt import XMouseListener
|
from com.sun.star.awt import XMouseListener
|
||||||
|
|
||||||
|
|
||||||
FILE_NAME_DEBUG = 'debug.log'
|
|
||||||
MSG_LANG = {
|
MSG_LANG = {
|
||||||
'es': {
|
'es': {
|
||||||
'OK': 'Aceptar',
|
'OK': 'Aceptar',
|
||||||
'Cancel': 'Cancelar',
|
'Cancel': 'Cancelar',
|
||||||
|
'Select file': 'Seleccionar archivo',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
|
||||||
DATE = '%d/%m/%Y %H:%M:%S'
|
FILE_NAME_DEBUG = 'zaz-debug.log'
|
||||||
|
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
|
||||||
|
LOG_DATE = '%d/%m/%Y %H:%M:%S'
|
||||||
LEVEL_ERROR = logging.getLevelName(logging.ERROR)
|
LEVEL_ERROR = logging.getLevelName(logging.ERROR)
|
||||||
LEVEL_DEBUG = logging.getLevelName(logging.DEBUG)
|
LEVEL_DEBUG = logging.getLevelName(logging.DEBUG)
|
||||||
LEVEL_INFO = logging.getLevelName(logging.INFO)
|
LEVEL_INFO = logging.getLevelName(logging.INFO)
|
||||||
logging.addLevelName(logging.ERROR, f'\033[1;41m{LEVEL_ERROR}\033[1;0m')
|
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.DEBUG, f'\x1b[33m{LEVEL_DEBUG}\033[1;0m')
|
||||||
logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m')
|
logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m')
|
||||||
logging.basicConfig(level=logging.DEBUG, format=FORMAT, datefmt=DATE)
|
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
OS = platform.system()
|
||||||
|
USER = getpass.getuser()
|
||||||
|
PC = platform.node()
|
||||||
|
DESKTOP = os.environ.get('DESKTOP_SESSION', '')
|
||||||
|
INFO_DEBUG = '{}\n\n{}\n\n{}'.format(sys.version, platform.platform(), '\n'.join(sys.path))
|
||||||
|
|
||||||
|
IS_WIN = OS == 'Windows'
|
||||||
|
LOG_NAME = 'ZAZ'
|
||||||
|
CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16'
|
||||||
|
|
||||||
|
CALC = 'calc'
|
||||||
|
WRITER = 'writer'
|
||||||
OBJ_CELL = 'ScCellObj'
|
OBJ_CELL = 'ScCellObj'
|
||||||
OBJ_RANGE = 'ScCellRangeObj'
|
OBJ_RANGE = 'ScCellRangeObj'
|
||||||
OBJ_RANGES = 'ScCellRangesObj'
|
OBJ_RANGES = 'ScCellRangesObj'
|
||||||
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
|
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
|
||||||
|
|
||||||
|
|
||||||
CTX = uno.getComponentContext()
|
CTX = uno.getComponentContext()
|
||||||
SM = CTX.getServiceManager()
|
SM = CTX.getServiceManager()
|
||||||
|
|
||||||
|
@ -96,17 +123,10 @@ def _get_config(key, node_name):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
OS = sys.platform
|
|
||||||
USER = getpass.getuser()
|
|
||||||
PC = platform.node()
|
|
||||||
|
|
||||||
LANGUAGE = _get_config('ooLocale', 'org.openoffice.Setup/L10N/')
|
LANGUAGE = _get_config('ooLocale', 'org.openoffice.Setup/L10N/')
|
||||||
|
LANG = LANGUAGE.split('-')[0]
|
||||||
NAME = TITLE = _get_config('ooName', 'org.openoffice.Setup/Product')
|
NAME = TITLE = _get_config('ooName', 'org.openoffice.Setup/Product')
|
||||||
VERSION = _get_config('ooSetupVersion', '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):
|
def mri(obj):
|
||||||
|
@ -120,7 +140,45 @@ def mri(obj):
|
||||||
return
|
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
|
||||||
|
|
||||||
|
|
||||||
|
class LogWin(object):
|
||||||
|
|
||||||
|
def __init__(self, doc):
|
||||||
|
self.doc = doc
|
||||||
|
|
||||||
|
def write(self, info):
|
||||||
|
text = self.doc.Text
|
||||||
|
cursor = text.createTextCursor()
|
||||||
|
cursor.gotoEnd(False)
|
||||||
|
text.insertString(cursor, str(info), 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def info(data):
|
||||||
|
log.info(data)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def debug(info):
|
def debug(info):
|
||||||
|
if IS_WIN:
|
||||||
|
# ~ app = LOApp(self.ctx, self.sm, self.desktop, self.toolkit)
|
||||||
|
# ~ doc = app.getDoc(FILE_NAME_DEBUG)
|
||||||
|
# ~ if not doc:
|
||||||
|
# ~ doc = app.newDoc(WRITER)
|
||||||
|
# ~ out = OutputDoc(doc)
|
||||||
|
# ~ sys.stdout = out
|
||||||
|
pprint(info)
|
||||||
|
return
|
||||||
|
|
||||||
log.debug(info)
|
log.debug(info)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -130,14 +188,11 @@ def error(info):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def catch_exception(f):
|
def save_log(path, data):
|
||||||
@wraps(f)
|
with open(path, 'a') as out:
|
||||||
def func(*args, **kwargs):
|
out.write('{} -{}- '.format(str(datetime.now())[:19], LOG_NAME))
|
||||||
try:
|
pprint(data, stream=out)
|
||||||
return f(*args, **kwargs)
|
return
|
||||||
except Exception as e:
|
|
||||||
log.error(f.__name__, exc_info=True)
|
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
def run_in_thread(fn):
|
def run_in_thread(fn):
|
||||||
|
@ -187,6 +242,10 @@ def get_desktop():
|
||||||
return create_instance('com.sun.star.frame.Desktop', True)
|
return create_instance('com.sun.star.frame.Desktop', True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_dispatch():
|
||||||
|
return create_instance('com.sun.star.frame.DispatchHelper')
|
||||||
|
|
||||||
|
|
||||||
def get_temp_file():
|
def get_temp_file():
|
||||||
return tempfile.NamedTemporaryFile()
|
return tempfile.NamedTemporaryFile()
|
||||||
|
|
||||||
|
@ -203,6 +262,20 @@ def _path_system(path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def exists_app(name):
|
||||||
|
try:
|
||||||
|
dn = subprocess.DEVNULL
|
||||||
|
subprocess.Popen([name, ''], stdout=dn, stderr=dn).terminate()
|
||||||
|
except OSError as e:
|
||||||
|
if e.errno == errno.ENOENT:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def exists(path):
|
||||||
|
return Path(path).exists()
|
||||||
|
|
||||||
|
|
||||||
def get_type_doc(obj):
|
def get_type_doc(obj):
|
||||||
services = {
|
services = {
|
||||||
'calc': 'com.sun.star.sheet.SpreadsheetDocument',
|
'calc': 'com.sun.star.sheet.SpreadsheetDocument',
|
||||||
|
@ -219,6 +292,11 @@ def get_type_doc(obj):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def _properties(values):
|
||||||
|
p = [PropertyValue(Name=n, Value=v) for n, v in values.items()]
|
||||||
|
return tuple(p)
|
||||||
|
|
||||||
|
|
||||||
# ~ Custom classes
|
# ~ Custom classes
|
||||||
|
|
||||||
|
|
||||||
|
@ -245,6 +323,10 @@ class LODocument(object):
|
||||||
def title(self):
|
def title(self):
|
||||||
return self.obj.getTitle()
|
return self.obj.getTitle()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def frame(self):
|
||||||
|
return self._cc.getFrame()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_saved(self):
|
def is_saved(self):
|
||||||
return self.obj.hasLocation()
|
return self.obj.hasLocation()
|
||||||
|
@ -281,6 +363,29 @@ class LODocument(object):
|
||||||
obj = self.obj.createInstance(name)
|
obj = self.obj.createInstance(name)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
def save(self, path='', **kwargs):
|
||||||
|
opt = _properties(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()
|
||||||
|
|
||||||
|
|
||||||
class LOCalc(LODocument):
|
class LOCalc(LODocument):
|
||||||
|
|
||||||
|
@ -313,9 +418,14 @@ class LOCalc(LODocument):
|
||||||
cell = LOCellRange(self.active[index].obj, self)
|
cell = LOCellRange(self.active[index].obj, self)
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
# ~ def create_instance(self, name):
|
def select(self, rango):
|
||||||
# ~ obj = self.obj.createInstance(name)
|
r = rango
|
||||||
# ~ return obj
|
if hasattr(rango, 'obj'):
|
||||||
|
r = rango.obj
|
||||||
|
elif isinstance(rango, str):
|
||||||
|
r = self.get_cell(rango).obj
|
||||||
|
self._cc.select(r)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class LOCalcSheet(object):
|
class LOCalcSheet(object):
|
||||||
|
@ -464,6 +574,11 @@ class LOBasicIde(LODocument):
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
super().__init__(obj)
|
super().__init__(obj)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def selection(self):
|
||||||
|
sel = self._cc.getSelection()
|
||||||
|
return sel
|
||||||
|
|
||||||
|
|
||||||
class LOCellRange(object):
|
class LOCellRange(object):
|
||||||
|
|
||||||
|
@ -587,6 +702,10 @@ class LOCellRange(object):
|
||||||
img.setSize(Size(w, h))
|
img.setSize(Size(w, h))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def select(self):
|
||||||
|
self.doc._cc.select(self.obj)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class EventsListenerBase(unohelper.Base, XEventListener):
|
class EventsListenerBase(unohelper.Base, XEventListener):
|
||||||
|
|
||||||
|
@ -926,6 +1045,7 @@ class LODialog(object):
|
||||||
}
|
}
|
||||||
return classes[tipo](obj)
|
return classes[tipo](obj)
|
||||||
|
|
||||||
|
@catch_exception
|
||||||
def add_control(self, properties):
|
def add_control(self, properties):
|
||||||
tipo = properties.pop('Type').lower()
|
tipo = properties.pop('Type').lower()
|
||||||
model = self.model.createInstance(self._get_control_model(tipo))
|
model = self.model.createInstance(self._get_control_model(tipo))
|
||||||
|
@ -998,3 +1118,377 @@ def set_properties(model, properties):
|
||||||
values = tuple(properties.values())
|
values = tuple(properties.values())
|
||||||
model.setPropertyValues(keys, values)
|
model.setPropertyValues(keys, values)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def get_file(filters=(), multiple=False):
|
||||||
|
file_picker = create_instance('com.sun.star.ui.dialogs.FilePicker')
|
||||||
|
file_picker.setTitle(_('Select file'))
|
||||||
|
file_picker.setMultiSelectionMode(multiple)
|
||||||
|
|
||||||
|
if filters:
|
||||||
|
file_picker.setCurrentFilter(filters[0][0])
|
||||||
|
for f in filters:
|
||||||
|
file_picker.appendFilter(f[0], f[1])
|
||||||
|
|
||||||
|
if file_picker.execute():
|
||||||
|
if multiple:
|
||||||
|
return [_path_system(f) for f in file_picker.getSelectedFiles()]
|
||||||
|
return _path_system(file_picker.getSelectedFiles()[0])
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
def get_info_path(path):
|
||||||
|
path, filename = os.path.split(path)
|
||||||
|
name, extension = os.path.splitext(filename)
|
||||||
|
return (path, filename, name, extension)
|
||||||
|
|
||||||
|
|
||||||
|
def inputbox(message, default='', title=TITLE):
|
||||||
|
|
||||||
|
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(dlg)
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
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 new_doc(type_doc=CALC):
|
||||||
|
path = 'private:factory/s{}'.format(type_doc)
|
||||||
|
doc = get_desktop().loadComponentFromURL(path, '_default', 0, ())
|
||||||
|
return _get_class_doc(doc)
|
||||||
|
|
||||||
|
|
||||||
|
def open_doc(path, **kwargs):
|
||||||
|
""" Open document in path
|
||||||
|
Usually options:
|
||||||
|
Hidden: True or False
|
||||||
|
AsTemplate: True or False
|
||||||
|
ReadOnly: True or False
|
||||||
|
Password: super_secret
|
||||||
|
MacroExecutionMode: 4 = Activate macros
|
||||||
|
Preview: True or False
|
||||||
|
|
||||||
|
http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1frame_1_1XComponentLoader.html
|
||||||
|
http://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1document_1_1MediaDescriptor.html
|
||||||
|
"""
|
||||||
|
path = _path_url(path)
|
||||||
|
opt = _properties(kwargs)
|
||||||
|
doc = get_desktop().loadComponentFromURL(path, '_blank', 0, opt)
|
||||||
|
if doc is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
return _get_class_doc(doc)
|
||||||
|
|
||||||
|
|
||||||
|
def open_file(path):
|
||||||
|
if IS_WIN:
|
||||||
|
os.startfile(path)
|
||||||
|
else:
|
||||||
|
subprocess.Popen(['xdg-open', path])
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def join(*paths):
|
||||||
|
return os.path.join(*paths)
|
||||||
|
|
||||||
|
|
||||||
|
def is_dir(path):
|
||||||
|
return Path(path).is_dir()
|
||||||
|
|
||||||
|
|
||||||
|
def is_file(path):
|
||||||
|
return Path(path).is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_size(path):
|
||||||
|
return Path(path).stat().st_size
|
||||||
|
|
||||||
|
|
||||||
|
def is_created(path):
|
||||||
|
return is_file(path) and bool(get_file_size(path))
|
||||||
|
|
||||||
|
|
||||||
|
def replace_ext(path, ext):
|
||||||
|
path, _, name, _ = get_info_path(path)
|
||||||
|
return '{}/{}.{}'.format(path, name, ext)
|
||||||
|
|
||||||
|
|
||||||
|
def zip_names(path):
|
||||||
|
with zipfile.ZipFile(path) as z:
|
||||||
|
names = z.namelist()
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
def run(command, wait=False):
|
||||||
|
# ~ debug(command)
|
||||||
|
# ~ debug(shlex.split(command))
|
||||||
|
try:
|
||||||
|
if wait:
|
||||||
|
# ~ p = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE)
|
||||||
|
# ~ p.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 = ("run [ERROR]: output = %s, error code = %s\n"
|
||||||
|
% (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)
|
||||||
|
|
||||||
|
|
||||||
|
def zip(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)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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 kill(path):
|
||||||
|
p = Path(path)
|
||||||
|
if p.is_file():
|
||||||
|
try:
|
||||||
|
p.unlink()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif p.is_dir():
|
||||||
|
p.rmdir()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
def get_clipboard():
|
||||||
|
df = None
|
||||||
|
text = ''
|
||||||
|
sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard')
|
||||||
|
transferable = sc.getContents()
|
||||||
|
data = transferable.getTransferDataFlavors()
|
||||||
|
for df in data:
|
||||||
|
if df.MimeType == CLIPBOARD_FORMAT_TEXT:
|
||||||
|
break
|
||||||
|
if df:
|
||||||
|
text = transferable.getTransferData(df)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
class TextTransferable(unohelper.Base, XTransferable):
|
||||||
|
"""Keep clipboard data and provide them."""
|
||||||
|
|
||||||
|
def __init__(self, text):
|
||||||
|
df = DataFlavor()
|
||||||
|
df.MimeType = CLIPBOARD_FORMAT_TEXT
|
||||||
|
df.HumanPresentableName = "encoded text utf-16"
|
||||||
|
self.flavors = [df]
|
||||||
|
self.data = [text]
|
||||||
|
|
||||||
|
def getTransferData(self, flavor):
|
||||||
|
if not flavor:
|
||||||
|
return
|
||||||
|
for i, f in enumerate(self.flavors):
|
||||||
|
if flavor.MimeType == f.MimeType:
|
||||||
|
return self.data[i]
|
||||||
|
return
|
||||||
|
|
||||||
|
def getTransferDataFlavors(self):
|
||||||
|
return tuple(self.flavors)
|
||||||
|
|
||||||
|
def isDataFlavorSupported(self, flavor):
|
||||||
|
if not flavor:
|
||||||
|
return False
|
||||||
|
mtype = flavor.MimeType
|
||||||
|
for f in self.flavors:
|
||||||
|
if mtype == f.MimeType:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def set_clipboard(text):
|
||||||
|
ts = TextTransferable(text)
|
||||||
|
sc = create_instance('com.sun.star.datatransfer.clipboard.SystemClipboard')
|
||||||
|
sc.setContents(ts, None)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def copy(doc=None):
|
||||||
|
if doc is None:
|
||||||
|
doc = get_document()
|
||||||
|
if hasattr(doc, 'frame'):
|
||||||
|
frame = doc.frame
|
||||||
|
else:
|
||||||
|
frame = doc.getCurrentController().getFrame()
|
||||||
|
dispatch = get_dispatch()
|
||||||
|
dispatch.executeDispatch(frame, '.uno:Copy', '', 0, ())
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def get_epoch():
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
return int(time.mktime(now.timetuple()))
|
||||||
|
|
4
zaz.py
4
zaz.py
|
@ -74,6 +74,10 @@ def _compress_oxt():
|
||||||
z.write(fullpath, file_name, zipfile.ZIP_DEFLATED)
|
z.write(fullpath, file_name, zipfile.ZIP_DEFLATED)
|
||||||
z.close()
|
z.close()
|
||||||
|
|
||||||
|
if DATA['update']:
|
||||||
|
path_xml = _join(path, FILES['update'])
|
||||||
|
_save(path_xml, DATA['update'])
|
||||||
|
|
||||||
log.info('Extension OXT created sucesfully...')
|
log.info('Extension OXT created sucesfully...')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue