diff --git a/CHANGELOG b/CHANGELOG index d83bb2a..21ee6c8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +v 0.4.0 [10-mar-2020] + - Update easymacro.py + - Fix: in OSx Catalina + + v 0.3.0 [12-nov-2019] - Update easymacro.py - Test install numpy diff --git a/README.md b/README.md index da201de..03d869f 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,10 @@ https://gitlab.com/mauriciobaeza/zaz This extension have a cost of maintenance of 1 euro every year. -BCH: `1RPLWHJW34p7pMQV1ft4x7eWhAYw69Dsb` +BCH: `qztd3l00xle5tffdqvh2snvadkuau2ml0uqm4n875d` +BTC: `3FhiXcXmAesmQzrNEngjHFnvaJRhU1AGWV` -BTC: `3Fe4JuADrAK8Qs7GDAxbSXR8E54avwZJLW` - -PayPal :( donate ATT elmau DOT net +You have others cryptos, welcome too! * [Look the wiki](https://gitlab.com/mauriciobaeza/zaz-pip/wikis/home) diff --git a/VERSION b/VERSION index 69367fd..26b5dec 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -0.3.0 +0.4.0 diff --git a/conf.py b/conf.py index 3643ab8..acd4846 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ import logging TYPE_EXTENSION = 1 # ~ https://semver.org/ -VERSION = '0.3.0' +VERSION = '0.4.0' # ~ Your great extension name, not used spaces NAME = 'ZAZPip' diff --git a/easymacro.py b/easymacro.py index 8e8e604..30ea714 100644 --- a/easymacro.py +++ b/easymacro.py @@ -129,12 +129,15 @@ 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' +IS_MAC = OS == 'Darwin' + LOG_NAME = 'ZAZ' CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16' PYTHON = 'python' if IS_WIN: PYTHON = 'python.exe' + CALC = 'calc' WRITER = 'writer' @@ -450,12 +453,14 @@ def call_dispatch(url, args=()): return -def get_temp_file(): +def get_temp_file(only_name=False): delete = True if IS_WIN: delete = False - return tempfile.NamedTemporaryFile(delete=delete) - + tmp = tempfile.NamedTemporaryFile(delete=delete) + if only_name: + tmp = tmp.name + return tmp def _path_url(path): if path.startswith('file://'): @@ -497,6 +502,11 @@ def dict_to_property(values, uno_any=False): return ps +def dict_to_named(values): + ps = tuple([NamedValue(n, v) for n, v in values.items()]) + return ps + + def property_to_dict(values): d = {i.Name: i.Value for i in values} return d @@ -722,6 +732,9 @@ class LODocument(object): return path_pdf + # ~ If location="document" Then + # ~ sp = ThisComponent.getScriptProvider() + class FormControlBase(object): EVENTS = { @@ -1650,7 +1663,7 @@ class LODrawImpress(LODocument): def insert_image(self, path, **kwargs): w = kwargs.get('width', 3000) - h = kwargs.get('Height', 1000) + h = kwargs.get('Height', 3000) x = kwargs.get('X', 1000) y = kwargs.get('Y', 1000) @@ -1799,6 +1812,15 @@ class LOCellRange(object): def columns(self): return self._obj.Columns.Count + @property + def row(self): + a = self.address + if hasattr(a, 'Row'): + r = a.Row + else: + r = a.StartRow + return r + @property def rows(self): return self._obj.Rows.Count @@ -1835,6 +1857,33 @@ class LOCellRange(object): self.sheet.obj.copyRange(self.address, source.range_address) return + def transpose(self, formula=False): + data = self.data + if formula: + data = self.formula + data = tuple(zip(*data)) + self.clear(1023) + self[0,0].copy_from(data, formula=formula) + return + + def transpose2(self): + # ~ 'Flags': 'A', + # ~ 'FormulaCommand': 0, + # ~ 'SkipEmptyCells': False, + # ~ 'AsLink': False, + # ~ 'MoveMode': 4, + args = { + 'Transpose': True, + } + args = dict_to_property(args) + self.select() + copy() + self.clear(1023) + self[0,0].select() + call_dispatch('.uno:InsertContents', args) + set_clipboard('') + return + def offset(self, row=1, col=0): ra = self.obj.getRangeAddress() col = ra.EndColumn + col @@ -1937,6 +1986,10 @@ class LOCellRange(object): def auto_format(self, value): self.obj.autoFormat(value) + def auto_width(self): + self.obj.Columns.OptimalWidth = True + return + def insert_image(self, path, **kwargs): s = self.obj.Size w = kwargs.get('width', s.Width) @@ -2058,6 +2111,22 @@ class LOCellRange(object): found = self.obj.replaceAll(descriptor) return found + @property + def validation(self): + return self.obj.Validation + @validation.setter + def validation(self, values): + is_list = False + current = self.validation + for k, v in values.items(): + if k == 'Type' and v == 6: + is_list = True + if k == 'Formula1' and is_list: + if isinstance(v, (tuple, list)): + v = ';'.join(['"{}"'.format(i) for i in v]) + setattr(current, k, v) + self.obj.Validation = current + class EventsListenerBase(unohelper.Base, XEventListener): @@ -2452,23 +2521,39 @@ class UnoBaseObject(object): return self._model.Width @width.setter def width(self, value): - if hasattr(self.model, 'Width'): - self.model.Width = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Width', value) + self.model.Width = value + + @property + def ps_width(self): + return self._get_possize('Width') + @ps_width.setter + def ps_width(self, value): + self._set_possize('Width', value) @property def height(self): - if hasattr(self.model, 'Height'): - return self.model.Height - ps = self.obj.getPosSize() - return ps.Height + return self.model.Height @height.setter def height(self, value): - if hasattr(self.model, 'Height'): - self.model.Height = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Height', value) + self.model.Height = value + + @property + def ps_height(self): + return self._get_possize('Height') + @ps_height.setter + def ps_height(self, value): + self._set_possize('Height', value) + + @property + def size(self): + ps = self.obj.getPosSize() + return (ps.Width, ps.Height) + @size.setter + def size(self, value): + ps = self.obj.getPosSize() + ps.Width = value[0] + ps.Height = value[1] + self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, SIZE) @property def tag(self): @@ -4065,6 +4150,10 @@ def active_cell(): return get_cell() +def active_sheet(): + return get_document().active + + def create_dialog(properties): return LODialog(**properties) @@ -4085,7 +4174,30 @@ def get_config_path(name='Work'): def get_path_python(): path = get_config_path('Module') - return join(path, PYTHON) + if IS_MAC: + path = join(path, '..', 'Resources', PYTHON) + else: + path = join(path, PYTHON) + + cmd = '"{}" -V'.format(path) + if run(cmd, True): + return path + + path = PYTHON + cmd = '"{}" -V'.format(path) + result = run(cmd, True) + + if 'Python 3' in result: + return path + + path = PYTHON + '3' + cmd = '"{}" -V'.format(path) + result = run(cmd, True) + + if 'Python 3' in result: + return path + + return '' # ~ Export ok @@ -4213,8 +4325,12 @@ def json_loads(data): def get_path_extension(id): + path = '' pip = CTX.getValueByName('/singletons/com.sun.star.deployment.PackageInformationProvider') - path = _path_system(pip.getPackageLocation(id)) + try: + path = _path_system(pip.getPackageLocation(id)) + except Exception as e: + error(e) return path @@ -4445,8 +4561,8 @@ def run(command, wait=False): 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)) + msg = ("%s\nrun [ERROR]: output = %s, error code = %s\n" + % (command, e.output, e.returncode)) error(msg) return False @@ -4487,7 +4603,7 @@ def _zippwd(source, target, pwd): # ~ Export ok -def zip(source, target='', mode='w', pwd=''): +def zip_files(source, target='', mode='w', pwd=''): if pwd: return _zippwd(source, target, pwd) diff --git a/files/ZAZPip_v0.3.0.oxt b/files/ZAZPip_v0.4.0.oxt similarity index 51% rename from files/ZAZPip_v0.3.0.oxt rename to files/ZAZPip_v0.4.0.oxt index e412bc5..727814a 100644 Binary files a/files/ZAZPip_v0.3.0.oxt and b/files/ZAZPip_v0.4.0.oxt differ diff --git a/source/META-INF/manifest.xml b/source/META-INF/manifest.xml index 0bce3f8..29ceecf 100644 --- a/source/META-INF/manifest.xml +++ b/source/META-INF/manifest.xml @@ -1,5 +1,5 @@ - + diff --git a/source/ZAZPip.py b/source/ZAZPip.py index 6473f17..72aa6a8 100644 --- a/source/ZAZPip.py +++ b/source/ZAZPip.py @@ -17,6 +17,8 @@ PACKAGES = { 'psycopg2-binary': 'ok.png', 'peewee': 'ok.png', 'numpy': 'ok.png', + 'pillow': 'ok.png', + 'pytesseract': 'ok.png', } @@ -30,9 +32,7 @@ class Controllers(object): def __init__(self, dialog): self.d = dialog - self.path_python = app.PYTHON - if app.IS_WIN: - self.path_python = app.get_path_python() + self.path_python = app.get_path_python() self._states = { 'list': False, 'install': False, @@ -58,9 +58,7 @@ class Controllers(object): def _install_pip(self): self.d.link_proyect.visible = False self.d.lst_log.visible = True - - with app.get_temp_file() as f: - path_pip = f.name + path_pip = app.get_temp_file(True) self.d.lst_log.insert('Download PIP...') data, err = app.url_open(URL_PIP, verify=False) @@ -103,9 +101,7 @@ class Controllers(object): return def _cmd_pip(self, args): - cmd = '{} {}'.format(PIP, args) - if app.IS_WIN: - cmd = '"{}" -m pip {}'.format(self.path_python, args) + cmd = '"{}" -m pip {}'.format(self.path_python, args) return cmd def cmd_admin_pip_action(self, event): @@ -250,10 +246,13 @@ class Controllers(object): cmd = '"{}"'.format(self.path_python) app.open_file(cmd) else: - if app.DESKTOP == 'gnome': - cmd = 'gnome-terminal -- {}'.format(self.path_python) - else: - cmd = 'exec {}'.format(self.path_python) + cmd = 'exec "{}"' + if app.IS_MAC: + cmd = 'open "{}"' + elif app.DESKTOP == 'gnome': + cmd = 'gnome-terminal -- {}' + + cmd = cmd.format(self.path_python) app.run(cmd) return @@ -271,7 +270,7 @@ class ZAZPip(unohelper.Base, XJobExecutor): def _create_dialog(self): args= { 'Name': 'dialog', - 'Title': 'ZAZ-PIP', + 'Title': 'Zaz-Pip', 'Width': 200, 'Height': 220, } @@ -279,30 +278,26 @@ class ZAZPip(unohelper.Base, XJobExecutor): dialog.id_extension = ID_EXTENSION dialog.events = Controllers(dialog) + lbl_title = '{} {} - {}'.format(app.NAME, app.VERSION, app.OS) args = { 'Type': 'Label', 'Name': 'lbl_title', - 'Label': 'ZAZ PIP', - 'Width': 50, + 'Label': lbl_title, + 'Width': 100, 'Height': 15, 'Border': 1, 'Align': 1, 'VerticalAlign': 1, 'Step': 10, - 'FontHeight': 15, + 'FontHeight': 12, } dialog.add_control(args) dialog.center(dialog.lbl_title, y=5) - path_python = app.PYTHON - if app.IS_WIN: - path_python = app.get_path_python() - - cmd = app.PYTHON + ' -V' - if app.IS_WIN: - cmd = '"{}" -V'.format(path_python) - + path_python = app.get_path_python() + cmd = '"{}" -V'.format(path_python) label = app.run(cmd, True) + args = { 'Type': 'Label', 'Name': 'lbl_python', @@ -313,13 +308,12 @@ class ZAZPip(unohelper.Base, XJobExecutor): 'Align': 1, 'VerticalAlign': 1, 'Step': 10, + 'FontHeight': 11, } dialog.add_control(args) dialog.center(dialog.lbl_python, y=25) - cmd = PIP + ' -V' - if app.IS_WIN: - cmd = '"{}" -m pip -V'.format(path_python) + cmd = '"{}" -m pip -V'.format(path_python) label = app.run(cmd, True) exists_pip = True if not label: diff --git a/source/description.xml b/source/description.xml index 015d124..3a29c42 100644 --- a/source/description.xml +++ b/source/description.xml @@ -1,7 +1,7 @@ - + ZAZ Pip ZAZ Pip diff --git a/source/pythonpath/easymacro.py b/source/pythonpath/easymacro.py index 8e8e604..30ea714 100644 --- a/source/pythonpath/easymacro.py +++ b/source/pythonpath/easymacro.py @@ -129,12 +129,15 @@ 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' +IS_MAC = OS == 'Darwin' + LOG_NAME = 'ZAZ' CLIPBOARD_FORMAT_TEXT = 'text/plain;charset=utf-16' PYTHON = 'python' if IS_WIN: PYTHON = 'python.exe' + CALC = 'calc' WRITER = 'writer' @@ -450,12 +453,14 @@ def call_dispatch(url, args=()): return -def get_temp_file(): +def get_temp_file(only_name=False): delete = True if IS_WIN: delete = False - return tempfile.NamedTemporaryFile(delete=delete) - + tmp = tempfile.NamedTemporaryFile(delete=delete) + if only_name: + tmp = tmp.name + return tmp def _path_url(path): if path.startswith('file://'): @@ -497,6 +502,11 @@ def dict_to_property(values, uno_any=False): return ps +def dict_to_named(values): + ps = tuple([NamedValue(n, v) for n, v in values.items()]) + return ps + + def property_to_dict(values): d = {i.Name: i.Value for i in values} return d @@ -722,6 +732,9 @@ class LODocument(object): return path_pdf + # ~ If location="document" Then + # ~ sp = ThisComponent.getScriptProvider() + class FormControlBase(object): EVENTS = { @@ -1650,7 +1663,7 @@ class LODrawImpress(LODocument): def insert_image(self, path, **kwargs): w = kwargs.get('width', 3000) - h = kwargs.get('Height', 1000) + h = kwargs.get('Height', 3000) x = kwargs.get('X', 1000) y = kwargs.get('Y', 1000) @@ -1799,6 +1812,15 @@ class LOCellRange(object): def columns(self): return self._obj.Columns.Count + @property + def row(self): + a = self.address + if hasattr(a, 'Row'): + r = a.Row + else: + r = a.StartRow + return r + @property def rows(self): return self._obj.Rows.Count @@ -1835,6 +1857,33 @@ class LOCellRange(object): self.sheet.obj.copyRange(self.address, source.range_address) return + def transpose(self, formula=False): + data = self.data + if formula: + data = self.formula + data = tuple(zip(*data)) + self.clear(1023) + self[0,0].copy_from(data, formula=formula) + return + + def transpose2(self): + # ~ 'Flags': 'A', + # ~ 'FormulaCommand': 0, + # ~ 'SkipEmptyCells': False, + # ~ 'AsLink': False, + # ~ 'MoveMode': 4, + args = { + 'Transpose': True, + } + args = dict_to_property(args) + self.select() + copy() + self.clear(1023) + self[0,0].select() + call_dispatch('.uno:InsertContents', args) + set_clipboard('') + return + def offset(self, row=1, col=0): ra = self.obj.getRangeAddress() col = ra.EndColumn + col @@ -1937,6 +1986,10 @@ class LOCellRange(object): def auto_format(self, value): self.obj.autoFormat(value) + def auto_width(self): + self.obj.Columns.OptimalWidth = True + return + def insert_image(self, path, **kwargs): s = self.obj.Size w = kwargs.get('width', s.Width) @@ -2058,6 +2111,22 @@ class LOCellRange(object): found = self.obj.replaceAll(descriptor) return found + @property + def validation(self): + return self.obj.Validation + @validation.setter + def validation(self, values): + is_list = False + current = self.validation + for k, v in values.items(): + if k == 'Type' and v == 6: + is_list = True + if k == 'Formula1' and is_list: + if isinstance(v, (tuple, list)): + v = ';'.join(['"{}"'.format(i) for i in v]) + setattr(current, k, v) + self.obj.Validation = current + class EventsListenerBase(unohelper.Base, XEventListener): @@ -2452,23 +2521,39 @@ class UnoBaseObject(object): return self._model.Width @width.setter def width(self, value): - if hasattr(self.model, 'Width'): - self.model.Width = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Width', value) + self.model.Width = value + + @property + def ps_width(self): + return self._get_possize('Width') + @ps_width.setter + def ps_width(self, value): + self._set_possize('Width', value) @property def height(self): - if hasattr(self.model, 'Height'): - return self.model.Height - ps = self.obj.getPosSize() - return ps.Height + return self.model.Height @height.setter def height(self, value): - if hasattr(self.model, 'Height'): - self.model.Height = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Height', value) + self.model.Height = value + + @property + def ps_height(self): + return self._get_possize('Height') + @ps_height.setter + def ps_height(self, value): + self._set_possize('Height', value) + + @property + def size(self): + ps = self.obj.getPosSize() + return (ps.Width, ps.Height) + @size.setter + def size(self, value): + ps = self.obj.getPosSize() + ps.Width = value[0] + ps.Height = value[1] + self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, SIZE) @property def tag(self): @@ -4065,6 +4150,10 @@ def active_cell(): return get_cell() +def active_sheet(): + return get_document().active + + def create_dialog(properties): return LODialog(**properties) @@ -4085,7 +4174,30 @@ def get_config_path(name='Work'): def get_path_python(): path = get_config_path('Module') - return join(path, PYTHON) + if IS_MAC: + path = join(path, '..', 'Resources', PYTHON) + else: + path = join(path, PYTHON) + + cmd = '"{}" -V'.format(path) + if run(cmd, True): + return path + + path = PYTHON + cmd = '"{}" -V'.format(path) + result = run(cmd, True) + + if 'Python 3' in result: + return path + + path = PYTHON + '3' + cmd = '"{}" -V'.format(path) + result = run(cmd, True) + + if 'Python 3' in result: + return path + + return '' # ~ Export ok @@ -4213,8 +4325,12 @@ def json_loads(data): def get_path_extension(id): + path = '' pip = CTX.getValueByName('/singletons/com.sun.star.deployment.PackageInformationProvider') - path = _path_system(pip.getPackageLocation(id)) + try: + path = _path_system(pip.getPackageLocation(id)) + except Exception as e: + error(e) return path @@ -4445,8 +4561,8 @@ def run(command, wait=False): 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)) + msg = ("%s\nrun [ERROR]: output = %s, error code = %s\n" + % (command, e.output, e.returncode)) error(msg) return False @@ -4487,7 +4603,7 @@ def _zippwd(source, target, pwd): # ~ Export ok -def zip(source, target='', mode='w', pwd=''): +def zip_files(source, target='', mode='w', pwd=''): if pwd: return _zippwd(source, target, pwd)