diff --git a/CHANGELOG b/CHANGELOG index 55de4f8..fdd2314 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +v 0.2.1 [16-sep-2019] + - Fix #1 + v 0.2.0 [14-sep-2019] --------------------- - Add support for spanish diff --git a/VERSION b/VERSION index 0ea3a94..cf74bd3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1,2 @@ -0.2.0 +0.2.1 + diff --git a/conf.py b/conf.py index 664155b..614eab2 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ import logging TYPE_EXTENSION = 1 # ~ https://semver.org/ -VERSION = '0.2.0' +VERSION = '0.2.1' # ~ Your great extension name, not used spaces NAME = 'ZAZBarCode' @@ -34,9 +34,19 @@ NAME = 'ZAZBarCode' # ~ Should be unique, used URL inverse ID = 'net.elmau.zaz.BarCode' -# ~ If you extension will be multilanguage set True -USE_LOCALES = False +# ~ If you extension will be multilanguage set: True +# ~ This feature used gettext, set pythonpath and easymacro in True +# ~ Yu can used PoEdit for edit PO files and generate MO files. +# ~ https://poedit.net/ +USE_LOCALES = True +DOMAIN = 'base' +PATH_LOCALES = 'locales' +# ~ locate pygettext.py +PATH_PYGETTEXT = '/usr/lib/python3.7/Tools/i18n/pygettext.py' +PATH_MSGMERGE = 'msgmerge' + +# ~ Show in extension manager PUBLISHER = { 'en': {'text': 'El Mau', 'link': 'https://gitlab.com/mauriciobaeza'}, 'es': {'text': 'El Mau', 'link': 'https://gitlab.com/mauriciobaeza'}, @@ -97,8 +107,14 @@ CONTEXT = { # ~ Menus, only for TYPE_EXTENSION = 1 # ~ Parent can be: AddonMenu or OfficeMenuBar # ~ For icons con name: NAME_16.bmp, used only NAME -# ~ PARENT = 'AddonMenu' -# ~ MENU_MAIN = '' +# ~ PARENT = '' +# ~ MENU_MAIN = {} +# ~ Shortcut: Key + "Modifier Keys" +# ~ Important: Not used any shortcuts used for LibreOffice +# ~ SHIFT is mapped to Shift on all platforms. +# ~ MOD1 is mapped to Ctrl on Windows/Linux, while it is mapped to Cmd on Mac. +# ~ MOD2 is mapped to Alt on all platforms. +# ~ For example: Shift+Ctrl+Alt+T -> T_SHIFT_MOD1_MOD2 PARENT = 'OfficeMenuBar' MENU_MAIN = { 'en': 'ZAZ BarCode', @@ -111,6 +127,7 @@ MENUS = ( 'context': 'calc,writer,impress,draw', 'icon': 'barcode', 'toolbar': False, + 'shortcut': 'I_SHIFT_MOD1_MOD2', }, { 'title': {'en': 'Insert CODE39', 'es': 'Insertar CODE39'}, @@ -247,11 +264,12 @@ EXTENSION = { 'name': NAME, 'id': ID, 'icon': (ICON, ICON_EXT), + 'languages': tuple(INFO.keys()) } # ~ If used more libraries set python path in True and copy inside -# ~ If used easymacro pythonpath always is True +# ~ If used easymacro pythonpath always is True, recommended DIRS = { 'meta': 'META-INF', 'source': 'source', @@ -259,8 +277,9 @@ DIRS = { 'images': 'images', 'registration': 'registration', 'files': 'files', - 'pythonpath': False, - 'locales': 'locales', + 'office': 'Office', + 'locales': PATH_LOCALES, + 'pythonpath': True, } @@ -276,6 +295,7 @@ FILES = { 'rdb': f'X{NAME}.rdb', 'update': f'{NAME.lower()}.update.xml', 'addin': 'CalcAddIn.xcu', + 'shortcut': 'Accelerators.xcu', 'easymacro': True, } @@ -528,7 +548,8 @@ if TYPE_EXTENSION == 3: FILE_MANIFEST = f""" - {NODE_ADDONS} + + {NODE_ADDONS} """ @@ -669,6 +690,55 @@ FILE_ADDIN = f""" """ +NODE_SHORTCUT = """ {0} + {0} + {0}service:{2}?{3} + {0} + {0} +""" + + +NODE_SHORTCUTS = '' +if TYPE_EXTENSION == 1: + node_global = [] + node_module = {} + for m in MENUS: + if not m.get('shortcut', ''): + continue + if m['context']: + for c in m['context'].split(','): + if not c in node_module: + node_module[c] = [] + node = NODE_SHORTCUT.format(' ', m['shortcut'], ID, m['argument']) + node_module[c].append(node) + continue + node = NODE_SHORTCUT.format('', m['shortcut'], ID, m['argument']) + node_global.append(node) + if node_global: + NODE_SHORTCUTS = ' \n' + NODE_SHORTCUTS += '\n'.join(node_global) + NODE_SHORTCUTS += ' ' + if node_module: + NODE_SHORTCUTS += ' \n' + for c, n in node_module.items(): + NODE_SHORTCUTS += ' \n'.format(CONTEXT[c]) + NODE_SHORTCUTS += '\n'.join(n) + NODE_SHORTCUTS += ' \n' + NODE_SHORTCUTS += ' ' + +FILE_SHORTCUTS = f""" + + +{NODE_SHORTCUTS} + + +""" + + DATA = { 'py': FILE_PY, 'manifest': FILE_MANIFEST, @@ -677,6 +747,7 @@ DATA = { 'update': FILE_UPDATE, 'idl': FILE_IDL, 'addin': FILE_ADDIN, + 'shortcut': FILE_SHORTCUTS, } diff --git a/easymacro.py b/easymacro.py index 622248c..15ea311 100644 --- a/easymacro.py +++ b/easymacro.py @@ -68,12 +68,9 @@ MSG_LANG = { 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.addLevelName(logging.ERROR, '\033[1;41mERROR\033[1;0m') +logging.addLevelName(logging.DEBUG, '\x1b[33mDEBUG\033[1;0m') +logging.addLevelName(logging.INFO, '\x1b[32mINFO\033[1;0m') logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE) log = logging.getLogger(__name__) @@ -176,10 +173,12 @@ def debug(info): # ~ doc = app.newDoc(WRITER) # ~ out = OutputDoc(doc) # ~ sys.stdout = out - pprint(info) + # ~ pprint(info) + doc = LogWin(new_doc('writer').obj) + doc.write(info) return - log.debug(info) + log.debug(str(info)) return @@ -203,6 +202,11 @@ def run_in_thread(fn): return run +def sleep(sec): + time.sleep(sec) + return + + def _(msg): L = LANGUAGE.split('-')[0] if L == 'en': @@ -247,7 +251,10 @@ def get_dispatch(): def get_temp_file(): - return tempfile.NamedTemporaryFile() + delete = True + if IS_WIN: + delete = False + return tempfile.NamedTemporaryFile(delete=delete) def _path_url(path): diff --git a/files/ZAZBarCode_v0.2.0.oxt b/files/ZAZBarCode_v0.2.0.oxt index 6487c55..3e0dc38 100644 Binary files a/files/ZAZBarCode_v0.2.0.oxt and b/files/ZAZBarCode_v0.2.0.oxt differ diff --git a/files/ZAZBarCode_v0.2.1.oxt b/files/ZAZBarCode_v0.2.1.oxt new file mode 100644 index 0000000..5e30629 Binary files /dev/null and b/files/ZAZBarCode_v0.2.1.oxt differ diff --git a/files/zazbarcode.update.xml b/files/zazbarcode.update.xml index 5788adf..09e7bae 100644 --- a/files/zazbarcode.update.xml +++ b/files/zazbarcode.update.xml @@ -5,10 +5,10 @@ xmlns:xlink="http://www.w3.org/1999/xlink"> - + - + diff --git a/source/META-INF/manifest.xml b/source/META-INF/manifest.xml index 559e3c0..a401fe8 100644 --- a/source/META-INF/manifest.xml +++ b/source/META-INF/manifest.xml @@ -1,5 +1,6 @@ + diff --git a/source/Office/Accelerators.xcu b/source/Office/Accelerators.xcu new file mode 100644 index 0000000..d290b14 --- /dev/null +++ b/source/Office/Accelerators.xcu @@ -0,0 +1,39 @@ + + + + + + + + service:net.elmau.zaz.BarCode?ask + + + + + + + service:net.elmau.zaz.BarCode?ask + + + + + + + service:net.elmau.zaz.BarCode?ask + + + + + + + service:net.elmau.zaz.BarCode?ask + + + + + + diff --git a/source/ZAZBarCode.py b/source/ZAZBarCode.py index d068ad3..1caf0c4 100644 --- a/source/ZAZBarCode.py +++ b/source/ZAZBarCode.py @@ -27,7 +27,6 @@ except Exception as e: class Controllers(object): - @app.catch_exception def __init__(self, dlg): self.d = dlg @@ -54,7 +53,6 @@ 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(): @@ -103,6 +101,8 @@ class ZAZBarCode(unohelper.Base, XJobExecutor): return cell = cell.offset() + if app.IS_WIN: + tf.close() cell.insert_image(tf.name) tf.close() return @@ -124,6 +124,8 @@ class ZAZBarCode(unohelper.Base, XJobExecutor): self._show_error(result) return + if app.IS_WIN: + tf.close() doc.insert_image(tf.name) tf.close() return @@ -136,6 +138,8 @@ class ZAZBarCode(unohelper.Base, XJobExecutor): self._show_error(result) return + if app.IS_WIN: + tf.close() doc.insert_image(tf.name) tf.close() return diff --git a/source/description.xml b/source/description.xml index 4d2d54a..02d2290 100644 --- a/source/description.xml +++ b/source/description.xml @@ -1,7 +1,7 @@ - + ZAZ Bar Code ZAZ Códigos de Barras diff --git a/source/pythonpath/easymacro.py b/source/pythonpath/easymacro.py index 622248c..15ea311 100644 --- a/source/pythonpath/easymacro.py +++ b/source/pythonpath/easymacro.py @@ -68,12 +68,9 @@ MSG_LANG = { 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.addLevelName(logging.ERROR, '\033[1;41mERROR\033[1;0m') +logging.addLevelName(logging.DEBUG, '\x1b[33mDEBUG\033[1;0m') +logging.addLevelName(logging.INFO, '\x1b[32mINFO\033[1;0m') logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=LOG_DATE) log = logging.getLogger(__name__) @@ -176,10 +173,12 @@ def debug(info): # ~ doc = app.newDoc(WRITER) # ~ out = OutputDoc(doc) # ~ sys.stdout = out - pprint(info) + # ~ pprint(info) + doc = LogWin(new_doc('writer').obj) + doc.write(info) return - log.debug(info) + log.debug(str(info)) return @@ -203,6 +202,11 @@ def run_in_thread(fn): return run +def sleep(sec): + time.sleep(sec) + return + + def _(msg): L = LANGUAGE.split('-')[0] if L == 'en': @@ -247,7 +251,10 @@ def get_dispatch(): def get_temp_file(): - return tempfile.NamedTemporaryFile() + delete = True + if IS_WIN: + delete = False + return tempfile.NamedTemporaryFile(delete=delete) def _path_url(path): diff --git a/source/pythonpath/qrcode/main.py b/source/pythonpath/qrcode/main.py index 7317372..5cbc2a8 100644 --- a/source/pythonpath/qrcode/main.py +++ b/source/pythonpath/qrcode/main.py @@ -1,8 +1,12 @@ +import struct +from bisect import bisect_left + from qrcode import constants, exceptions, util from qrcode.image.base import BaseImage -import six -from bisect import bisect_left + +def int2byte(value): + return struct.Struct('>B').pack(value) def make(data=None, **kwargs): @@ -236,7 +240,7 @@ class QRCode(object): self.make() modcount = self.modules_count - codes = [six.int2byte(code).decode('cp437') + codes = [int2byte(code).decode('cp437') for code in (255, 223, 220, 219)] if tty: invert = True @@ -377,7 +381,7 @@ class QRCode(object): data_len = len(data) - for col in six.moves.xrange(self.modules_count - 1, 0, -2): + for col in range(self.modules_count - 1, 0, -2): if col <= 6: col -= 1 diff --git a/source/pythonpath/qrcode/util.py b/source/pythonpath/qrcode/util.py index 58f3d21..74ab39f 100644 --- a/source/pythonpath/qrcode/util.py +++ b/source/pythonpath/qrcode/util.py @@ -1,8 +1,8 @@ import re import math -import six -from six.moves import xrange +# ~ import six +# ~ from six.moves import xrange from qrcode import base, exceptions, LUT @@ -32,8 +32,10 @@ MODE_SIZE_LARGE = { MODE_KANJI: 12, } -ALPHA_NUM = six.b('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:') -RE_ALPHA_NUM = re.compile(six.b('^[') + re.escape(ALPHA_NUM) + six.b(r']*\Z')) + +ALPHA_NUM = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.encode("latin-1") +RE_ALPHA_NUM = re.compile('^['.encode("latin-1") + re.escape(ALPHA_NUM) + r']*\Z'.encode("latin-1")) + # The number of bits for numeric delimited data lengths. NUMBER_LENGTH = {3: 10, 2: 7, 1: 4} @@ -96,8 +98,8 @@ PAD1 = 0x11 _data_count = lambda block: block.data_count BIT_LIMIT_TABLE = [ [0] + [8*sum(map(_data_count, base.rs_blocks(version, error_correction))) - for version in xrange(1, 41)] - for error_correction in xrange(4) + for version in range(1, 41)] + for error_correction in range(4) ] @@ -192,7 +194,7 @@ def lost_point(modules): def _lost_point_level1(modules, modules_count): lost_point = 0 - modules_range = xrange(modules_count) + modules_range = range(modules_count) container = [0] * (modules_count + 1) for row in modules_range: @@ -225,7 +227,7 @@ def _lost_point_level1(modules, modules_count): container[length] += 1 lost_point += sum(container[each_length] * (each_length - 2) - for each_length in xrange(5, modules_count + 1)) + for each_length in range(5, modules_count + 1)) return lost_point @@ -233,7 +235,7 @@ def _lost_point_level1(modules, modules_count): def _lost_point_level2(modules, modules_count): lost_point = 0 - modules_range = xrange(modules_count - 1) + modules_range = range(modules_count - 1) for row in modules_range: this_row = modules[row] next_row = modules[row + 1] @@ -262,8 +264,8 @@ def _lost_point_level3(modules, modules_count): # row/column, preceded or followed by light area 4 modules wide. From ISOIEC. # pattern1: 10111010000 # pattern2: 00001011101 - modules_range = xrange(modules_count) - modules_range_short = xrange(modules_count-10) + modules_range = range(modules_count) + modules_range_short = range(modules_count-10) lost_point = 0 for row in modules_range: @@ -348,14 +350,14 @@ def optimal_data_chunks(data, minimum=4): :param minimum: The minimum number of bytes in a row to split as a chunk. """ data = to_bytestring(data) - num_pattern = six.b(r'\d') - alpha_pattern = six.b('[') + re.escape(ALPHA_NUM) + six.b(']') + num_pattern = r'\d'.encode("latin-1") + alpha_pattern = '['.encode("latin-1") + re.escape(ALPHA_NUM) + ']'.encode("latin-1") if len(data) <= minimum: - num_pattern = re.compile(six.b('^') + num_pattern + six.b('+$')) - alpha_pattern = re.compile(six.b('^') + alpha_pattern + six.b('+$')) + num_pattern = re.compile('^'.encode("latin-1") + num_pattern + '+$'.encode("latin-1")) + alpha_pattern = re.compile('^'.encode("latin-1") + alpha_pattern + '+$'.encode("latin-1")) else: re_repeat = ( - six.b('{') + six.text_type(minimum).encode('ascii') + six.b(',}')) + '{'.encode("latin-1") + str(minimum).encode('ascii') + ',}'.encode("latin-1")) num_pattern = re.compile(num_pattern + re_repeat) alpha_pattern = re.compile(alpha_pattern + re_repeat) num_bits = _optimal_split(data, num_pattern) @@ -390,8 +392,8 @@ def to_bytestring(data): Convert data to a (utf-8 encoded) byte-string if it isn't a byte-string already. """ - if not isinstance(data, six.binary_type): - data = six.text_type(data).encode('utf-8') + if not isinstance(data, bytes): + data = str(data).encode('utf-8') return data @@ -439,12 +441,12 @@ class QRData(object): def write(self, buffer): if self.mode == MODE_NUMBER: - for i in xrange(0, len(self.data), 3): + for i in range(0, len(self.data), 3): chars = self.data[i:i + 3] bit_length = NUMBER_LENGTH[len(chars)] buffer.put(int(chars), bit_length) elif self.mode == MODE_ALPHA_NUM: - for i in xrange(0, len(self.data), 2): + for i in range(0, len(self.data), 2): chars = self.data[i:i + 2] if len(chars) > 1: buffer.put( @@ -453,12 +455,13 @@ class QRData(object): else: buffer.put(ALPHA_NUM.find(chars), 6) else: - if six.PY3: + # ~ if six.PY3: # Iterating a bytestring in Python 3 returns an integer, # no need to ord(). - data = self.data - else: - data = [ord(c) for c in self.data] + # ~ data = self.data + # ~ else: + # ~ data = [ord(c) for c in self.data] + data = self.data for c in data: buffer.put(c, 8) diff --git a/zaz.py b/zaz.py index 92c0533..5669ec1 100644 --- a/zaz.py +++ b/zaz.py @@ -20,6 +20,7 @@ import argparse import os import sys +from pathlib import Path from shutil import copyfile from subprocess import call import zipfile @@ -32,6 +33,7 @@ from conf import ( INFO, PATHS, TYPE_EXTENSION, + USE_LOCALES, log) @@ -44,7 +46,7 @@ def _join(*paths): def _mkdir(path): - return os.mkdir(path) + return Path(path).mkdir(parents=True, exist_ok=True) def _save(path, data): @@ -112,6 +114,8 @@ def _create_new_directories(): _mkdir(path) path = _join(path_source, DIRS['registration']) _mkdir(path) + path = _join(path_source, DIRS['office']) + _mkdir(path) if FILES['easymacro'] or DIRS['pythonpath']: path = _join(path_source, 'pythonpath') @@ -221,6 +225,11 @@ def _update_files(): path = _join(path_source, DIRS['meta'], FILES['manifest']) _save(path, DATA['manifest']) + path = _join(path_source, DIRS['office']) + _mkdir(path) + path = _join(path_source, DIRS['office'], FILES['shortcut']) + _save(path, DATA['shortcut']) + path = _join(path_source, FILES['addons']) _save(path, DATA['addons']) @@ -231,6 +240,13 @@ def _update_files(): path = _join(path_source, FILES['addin']) _save(path, DATA['addin']) + if USE_LOCALES: + msg = "Don't forget generate DOMAIN.pot for locales" + log.info(msg) + for lang in EXTENSION['languages']: + path = _join(path_source, DIRS['locales'], lang, 'LC_MESSAGES') + Path(path).mkdir(parents=True, exist_ok=True) + _compile_idl() return