Add support for locales

This commit is contained in:
Mauricio Baeza 2019-09-14 15:19:45 -05:00
parent 614d80e479
commit 358937cd19
19 changed files with 1296 additions and 99 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
__pycache__/
*.py[cod]
*.log
images/
docs/
# Virtualenv
.env/
virtual/

View File

@ -1 +1 @@
0.1.0
0.2.0

Binary file not shown.

Binary file not shown.

70
conf.py
View File

@ -26,7 +26,7 @@ import logging
TYPE_EXTENSION = 1
# ~ https://semver.org/
VERSION = '0.1.0'
VERSION = '0.2.0'
# ~ Your great extension name, not used spaces
NAME = 'ZAZBarCode'
@ -34,6 +34,9 @@ NAME = 'ZAZBarCode'
# ~ Should be unique, used URL inverse
ID = 'net.elmau.zaz.BarCode'
# ~ If you extension will be multilanguage set True
USE_LOCALES = False
PUBLISHER = {
'en': {'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
INFO = {
'en': {
'display_name': 'ZAZ Bar Code',
@ -258,6 +260,7 @@ DIRS = {
'registration': 'registration',
'files': 'files',
'pythonpath': False,
'locales': 'locales',
}
@ -279,16 +282,21 @@ FILES = {
# ~ URLs for update for example
# ~ URL_XML_UPDATE = 'https://gitlab.com/USER/PROYECT/raw/BRANCH/FOLDERs/FILE_NAME'
URL_XML_UPDATE = ''
URL_OXT = ''
URL_BASE = 'https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/'
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 = {
'idlc': '/usr/lib/libreoffice/sdk/bin/idlc',
'include': '/usr/share/idl/libreoffice',
'regmerge': '/usr/lib/libreoffice/program/regmerge',
'soffice': ('soffice', '--calc', FILE_TEST),
'soffice': ('soffice', PROGRAM, FILE_TEST),
'install': ('unopkg', 'add', '-v', '-f', '-s'),
}
@ -445,6 +453,8 @@ if PARENT == 'OfficeMenuBar':
def _get_context(args):
if not args:
return ''
c = []
for v in args.split(','):
c.append(CONTEXT[v])
@ -472,29 +482,31 @@ for i, m in enumerate(MENUS):
toolbar.append(NODE_MENU.format(**values))
NODE_TOOLBAR = ''
if PARENT == 'AddonMenu':
NODE_MENUS = '\n'.join(menus)
else:
tmp = ' <value xml:lang="{}">{}</value>'
titles = '\n'.join([tmp.format(k, v) for k, v in MENU_MAIN.items()])
SUBMENUS = '<node oor:name="Submenu">\n ' + '\n'.join(menus) + '\n </node>'
NODE_MENUS = f""" <node oor:name="{ID}" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
{titles}
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
{SUBMENUS}
</node>"""
NODE_MENUS = ''
if TYPE_EXTENSION == 1:
if PARENT == 'AddonMenu':
NODE_MENUS = '\n'.join(menus)
else:
tmp = ' <value xml:lang="{}">{}</value>'
titles = '\n'.join([tmp.format(k, v) for k, v in MENU_MAIN.items()])
SUBMENUS = '<node oor:name="Submenu">\n ' + '\n'.join(menus) + '\n </node>'
NODE_MENUS = f""" <node oor:name="{ID}" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
{titles}
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
{SUBMENUS}
</node>"""
if toolbar:
node_toolbars = '\n'.join(toolbar)
NODE_TOOLBAR = f""" <node oor:name="OfficeToolBar">
<node oor:name="{ID}" oor:op="replace">
{node_toolbars}
</node>
</node>"""
if toolbar:
node_toolbars = '\n'.join(toolbar)
NODE_TOOLBAR = f""" <node oor:name="OfficeToolBar">
<node oor:name="{ID}" oor:op="replace">
{node_toolbars}
</node>
</node>"""
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">
@ -668,5 +680,5 @@ DATA = {
}
# ~ LICENSE_ACCEPT_BY = 'admin' # or admin
# ~ LICENSE_ACCEPT_BY = 'user' # or admin
# ~ LICENSE_SUPPRESS_ON_UPDATE = True

View File

@ -18,15 +18,26 @@
# ~ along with ZAZ. If not, see <https://www.gnu.org/licenses/>.
import ctypes
import datetime
import errno
import getpass
import logging
import os
import platform
import shlex
import subprocess
import sys
import tempfile
import threading
import time
import zipfile
from datetime import datetime
from functools import wraps
from pathlib import Path, PurePath
from pprint import pprint
from subprocess import PIPE
import uno
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.PosSize import POSSIZE, SIZE
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.text.TextContentAnchorType import AS_CHARACTER
@ -44,31 +56,46 @@ from com.sun.star.awt import XActionListener
from com.sun.star.awt import XMouseListener
FILE_NAME_DEBUG = 'debug.log'
MSG_LANG = {
'es': {
'OK': 'Aceptar',
'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_DEBUG = logging.getLevelName(logging.DEBUG)
LEVEL_INFO = logging.getLevelName(logging.INFO)
logging.addLevelName(logging.ERROR, f'\033[1;41m{LEVEL_ERROR}\033[1;0m')
logging.addLevelName(logging.DEBUG, f'\x1b[33m{LEVEL_DEBUG}\033[1;0m')
logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m')
logging.basicConfig(level=logging.DEBUG, format=FORMAT, datefmt=DATE)
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
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_RANGE = 'ScCellRangeObj'
OBJ_RANGES = 'ScCellRangesObj'
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
CTX = uno.getComponentContext()
SM = CTX.getServiceManager()
@ -96,17 +123,10 @@ def _get_config(key, node_name):
return ''
OS = sys.platform
USER = getpass.getuser()
PC = platform.node()
LANGUAGE = _get_config('ooLocale', 'org.openoffice.Setup/L10N/')
LANG = LANGUAGE.split('-')[0]
NAME = TITLE = _get_config('ooName', 'org.openoffice.Setup/Product')
VERSION = _get_config('ooSetupVersion', 'org.openoffice.Setup/Product')
# ~ DESKTOP = create_instance('com.sun.star.frame.Desktop', True)
INFO_DEBUG = '{}\n\n{}\n\n{}'.format(
sys.version, platform.platform(), '\n'.join(sys.path))
def mri(obj):
@ -120,7 +140,45 @@ def mri(obj):
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):
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)
return
@ -130,14 +188,11 @@ def error(info):
return
def catch_exception(f):
@wraps(f)
def func(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
log.error(f.__name__, exc_info=True)
return func
def save_log(path, data):
with open(path, 'a') as out:
out.write('{} -{}- '.format(str(datetime.now())[:19], LOG_NAME))
pprint(data, stream=out)
return
def run_in_thread(fn):
@ -187,6 +242,10 @@ def get_desktop():
return create_instance('com.sun.star.frame.Desktop', True)
def get_dispatch():
return create_instance('com.sun.star.frame.DispatchHelper')
def get_temp_file():
return tempfile.NamedTemporaryFile()
@ -203,6 +262,20 @@ def _path_system(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):
services = {
'calc': 'com.sun.star.sheet.SpreadsheetDocument',
@ -219,6 +292,11 @@ def get_type_doc(obj):
return ''
def _properties(values):
p = [PropertyValue(Name=n, Value=v) for n, v in values.items()]
return tuple(p)
# ~ Custom classes
@ -245,6 +323,10 @@ class LODocument(object):
def title(self):
return self.obj.getTitle()
@property
def frame(self):
return self._cc.getFrame()
@property
def is_saved(self):
return self.obj.hasLocation()
@ -281,6 +363,29 @@ class LODocument(object):
obj = self.obj.createInstance(name)
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):
@ -313,9 +418,14 @@ class LOCalc(LODocument):
cell = LOCellRange(self.active[index].obj, self)
return cell
# ~ def create_instance(self, name):
# ~ obj = self.obj.createInstance(name)
# ~ return obj
def select(self, rango):
r = rango
if hasattr(rango, 'obj'):
r = rango.obj
elif isinstance(rango, str):
r = self.get_cell(rango).obj
self._cc.select(r)
return
class LOCalcSheet(object):
@ -464,6 +574,11 @@ class LOBasicIde(LODocument):
def __init__(self, obj):
super().__init__(obj)
@property
def selection(self):
sel = self._cc.getSelection()
return sel
class LOCellRange(object):
@ -587,6 +702,10 @@ class LOCellRange(object):
img.setSize(Size(w, h))
return
def select(self):
self.doc._cc.select(self.obj)
return
class EventsListenerBase(unohelper.Base, XEventListener):
@ -926,6 +1045,7 @@ class LODialog(object):
}
return classes[tipo](obj)
@catch_exception
def add_control(self, properties):
tipo = properties.pop('Type').lower()
model = self.model.createInstance(self._get_control_model(tipo))
@ -998,3 +1118,377 @@ def set_properties(model, properties):
values = tuple(properties.values())
model.setPropertyValues(keys, values)
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.

BIN
files/ZAZBarCode_v0.2.0.oxt Normal file

Binary file not shown.

View File

@ -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>

View File

@ -3,14 +3,14 @@
<node oor:name="AddonUI">
<node oor:name="OfficeMenuBar">
<node oor:name="net.elmau.zaz.BarCode" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">ZAZ BarCode</value>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">ZAZ BarCode</value>
<value xml:lang="es">ZAZ BarCode</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<node oor:name="Submenu">
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<node oor:name="Submenu">
<node oor:name="net.elmau.zaz.BarCode.101" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert BarCode</value>
@ -318,7 +318,7 @@
</prop>
</node>
</node>
</node>
</node>
</node>
</node>

View File

@ -1,13 +1,13 @@
import gettext
import uno
import unohelper
from com.sun.star.task import XJobExecutor
import easymacro as app
import qrcode
import qrcode.image.svg as svg
from barcode import generate
import easymacro as app
ID_EXTENSION = 'net.elmau.zaz.BarCode'
SERVICE = ('com.sun.star.task.Job',)
@ -15,20 +15,31 @@ TITLE = 'ZAZ BarCode'
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):
@app.catch_exception
def __init__(self, dlg):
self.d = dlg
def button_action(self, event):
if not self.d.listbox.value:
self.d.listbox.set_focus()
msg = 'Select barcode type'
msg = _('Select barcode type')
app.warning(msg, TITLE)
return
if not self.d.text.value.strip():
self.d.text.set_focus()
msg = 'Data field is mandatory'
msg = _('Data field is mandatory')
app.warning(msg, TITLE)
return
@ -43,6 +54,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
self._data = ''
self._type = ''
@app.catch_exception
def trigger(self, args):
self._type = args
if args == 'ask' and not self._get_values():
@ -79,7 +91,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
if not self._data:
self._data = cell.value
if not self._data:
msg = 'Select data'
msg = _('Select data')
self._show_error(msg)
return
@ -101,7 +113,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
if not self._data:
self._data = sel.string
if not self._data:
msg = 'Select data'
msg = _('Select data')
self._show_error(msg)
return
@ -133,7 +145,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
return
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.errorbox(msg, TITLE)
return
@ -151,12 +163,11 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
args = {
'Type': 'Label',
'Name': 'lbl_barcode',
'Label': 'Select barcode type',
'Width': 55,
'Label': _('~Select barcode type'),
'Width': 70,
'Height': 15,
'X': 10,
'Y': 10,
'Align': 2,
'VerticalAlign': 1,
}
dlg.add_control(args)
@ -164,8 +175,8 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
args = {
'Type': 'Label',
'Name': 'lbl_data',
'Label': 'Capture data for barcode',
'Width': 70,
'Label': _('~Capture data for barcode'),
'Width': 100,
'Height': 15,
'VerticalAlign': 1,
}
@ -174,7 +185,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
args = {
'Type': 'ListBox',
'Name': 'listbox',
'Width': 80,
'Width': 65,
'Height': 15,
'Dropdown': True,
}
@ -197,7 +208,7 @@ class ZAZBarCode(unohelper.Base, XJobExecutor):
args = {
'Type': 'Button',
'Name': 'button',
'Label': 'Insert Barcode',
'Label': _('~Insert Barcode'),
'Width': 60,
'Height': 15,
}

View File

@ -1,7 +1,7 @@
<?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">
<identifier value="net.elmau.zaz.BarCode" />
<version value="0.1.0" />
<version value="0.2.0" />
<display-name>
<name lang="en">ZAZ Bar Code</name>
<name lang="es">ZAZ Códigos de Barras</name>
@ -23,4 +23,7 @@
<license-text xlink:href="registration/license_es.txt" lang="es" />
</simple-license>
</registration>
<update-information>
<src xlink:href="https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/zazbarcode.update.xml" />
</update-information>
</description>

48
source/locales/base.pot Normal file
View File

@ -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.

View File

@ -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.

View File

@ -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"

View File

@ -18,15 +18,26 @@
# ~ along with ZAZ. If not, see <https://www.gnu.org/licenses/>.
import ctypes
import datetime
import errno
import getpass
import logging
import os
import platform
import shlex
import subprocess
import sys
import tempfile
import threading
import time
import zipfile
from datetime import datetime
from functools import wraps
from pathlib import Path, PurePath
from pprint import pprint
from subprocess import PIPE
import uno
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.PosSize import POSSIZE, SIZE
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.text.TextContentAnchorType import AS_CHARACTER
@ -44,31 +56,46 @@ from com.sun.star.awt import XActionListener
from com.sun.star.awt import XMouseListener
FILE_NAME_DEBUG = 'debug.log'
MSG_LANG = {
'es': {
'OK': 'Aceptar',
'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_DEBUG = logging.getLevelName(logging.DEBUG)
LEVEL_INFO = logging.getLevelName(logging.INFO)
logging.addLevelName(logging.ERROR, f'\033[1;41m{LEVEL_ERROR}\033[1;0m')
logging.addLevelName(logging.DEBUG, f'\x1b[33m{LEVEL_DEBUG}\033[1;0m')
logging.addLevelName(logging.INFO, f'\x1b[32m{LEVEL_INFO}\033[1;0m')
logging.basicConfig(level=logging.DEBUG, format=FORMAT, datefmt=DATE)
logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE)
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_RANGE = 'ScCellRangeObj'
OBJ_RANGES = 'ScCellRangesObj'
OBJ_TYPE_RANGES = (OBJ_CELL, OBJ_RANGE, OBJ_RANGES)
CTX = uno.getComponentContext()
SM = CTX.getServiceManager()
@ -96,17 +123,10 @@ def _get_config(key, node_name):
return ''
OS = sys.platform
USER = getpass.getuser()
PC = platform.node()
LANGUAGE = _get_config('ooLocale', 'org.openoffice.Setup/L10N/')
LANG = LANGUAGE.split('-')[0]
NAME = TITLE = _get_config('ooName', 'org.openoffice.Setup/Product')
VERSION = _get_config('ooSetupVersion', 'org.openoffice.Setup/Product')
# ~ DESKTOP = create_instance('com.sun.star.frame.Desktop', True)
INFO_DEBUG = '{}\n\n{}\n\n{}'.format(
sys.version, platform.platform(), '\n'.join(sys.path))
def mri(obj):
@ -120,7 +140,45 @@ def mri(obj):
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):
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)
return
@ -130,14 +188,11 @@ def error(info):
return
def catch_exception(f):
@wraps(f)
def func(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
log.error(f.__name__, exc_info=True)
return func
def save_log(path, data):
with open(path, 'a') as out:
out.write('{} -{}- '.format(str(datetime.now())[:19], LOG_NAME))
pprint(data, stream=out)
return
def run_in_thread(fn):
@ -187,6 +242,10 @@ def get_desktop():
return create_instance('com.sun.star.frame.Desktop', True)
def get_dispatch():
return create_instance('com.sun.star.frame.DispatchHelper')
def get_temp_file():
return tempfile.NamedTemporaryFile()
@ -203,6 +262,20 @@ def _path_system(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):
services = {
'calc': 'com.sun.star.sheet.SpreadsheetDocument',
@ -219,6 +292,11 @@ def get_type_doc(obj):
return ''
def _properties(values):
p = [PropertyValue(Name=n, Value=v) for n, v in values.items()]
return tuple(p)
# ~ Custom classes
@ -245,6 +323,10 @@ class LODocument(object):
def title(self):
return self.obj.getTitle()
@property
def frame(self):
return self._cc.getFrame()
@property
def is_saved(self):
return self.obj.hasLocation()
@ -281,6 +363,29 @@ class LODocument(object):
obj = self.obj.createInstance(name)
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):
@ -313,9 +418,14 @@ class LOCalc(LODocument):
cell = LOCellRange(self.active[index].obj, self)
return cell
# ~ def create_instance(self, name):
# ~ obj = self.obj.createInstance(name)
# ~ return obj
def select(self, rango):
r = rango
if hasattr(rango, 'obj'):
r = rango.obj
elif isinstance(rango, str):
r = self.get_cell(rango).obj
self._cc.select(r)
return
class LOCalcSheet(object):
@ -464,6 +574,11 @@ class LOBasicIde(LODocument):
def __init__(self, obj):
super().__init__(obj)
@property
def selection(self):
sel = self._cc.getSelection()
return sel
class LOCellRange(object):
@ -587,6 +702,10 @@ class LOCellRange(object):
img.setSize(Size(w, h))
return
def select(self):
self.doc._cc.select(self.obj)
return
class EventsListenerBase(unohelper.Base, XEventListener):
@ -926,6 +1045,7 @@ class LODialog(object):
}
return classes[tipo](obj)
@catch_exception
def add_control(self, properties):
tipo = properties.pop('Type').lower()
model = self.model.createInstance(self._get_control_model(tipo))
@ -998,3 +1118,377 @@ def set_properties(model, properties):
values = tuple(properties.values())
model.setPropertyValues(keys, values)
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
View File

@ -74,6 +74,10 @@ def _compress_oxt():
z.write(fullpath, file_name, zipfile.ZIP_DEFLATED)
z.close()
if DATA['update']:
path_xml = _join(path, FILES['update'])
_save(path_xml, DATA['update'])
log.info('Extension OXT created sucesfully...')
return