import uno import unohelper from com.sun.star.task import XJobExecutor import easymacro as app ID_EXTENSION = 'net.elmau.zaz.pip' SERVICE = ('com.sun.star.task.Job',) TITLE = 'ZAZ-PIP' URL_PIP = 'https://bootstrap.pypa.io/get-pip.py' PIP = 'pip' PACKAGES = { 'psycopg2-binary': 'ok.png', 'peewee': 'ok.png', 'numpy': 'ok.png', 'pillow': 'ok.png', 'pytesseract': 'ok.png', } _ = app.install_locales(__file__) class Controllers(object): OK1 = 'Successfully installed' OK2 = 'Requirement already' OK3 = 'Successfully uninstalled' def __init__(self, dialog): self.d = dialog # ~ self.path_python = app.PYTHON # ~ if app.IS_WIN: self.path_python = app.get_path_python() self._states = { 'list': False, 'install': False, 'search': False, 'versions': False, } def _set_state(self, state): for k in self._states.keys(): self._states[k] = False self._states[state] = True return def cmd_install_pip_action(self, event): msg = _('Do you want install PIP?') if not app.question(msg, 'ZAZ-Pip'): return self._install_pip() return @app.run_in_thread def _install_pip(self): self.d.link_proyect.visible = False self.d.lst_log.visible = True path_pip = app.get_temp_file(True) self.d.lst_log.insert('Download PIP...') data, err = app.url_open(URL_PIP, verify=False) if err: msg = _('Do you have internet connection?') app.errorbox('{}\n\n{}'.format(msg, err)) return app.save_file(path_pip, 'wb', data) if not app.is_created(path_pip): msg = _('File PIP not save') app.errorbox(msg) return self.d.lst_log.insert(_('PIP save correctly...')) try: self.d.lst_log.insert(_('Start installing PIP...')) cmd = '"{}" "{}" --user'.format(self.path_python, path_pip) for line in app.popen(cmd): if isinstance(line, tuple): app.errorbox(line) break self.d.lst_log.insert(line) cmd = self._cmd_pip('-V') label = app.run(cmd, True) if label: self.d.lbl_pip.value = label self.d.cmd_install_pip.visible = False self.d.cmd_admin_pip.visible = True msg = _('PIP installed sucesfully') app.msgbox(msg) else: msg = _('PIP not installed, see log') app.warning(msg) except Exception as e: app.errorbox(e) return def _cmd_pip(self, args): cmd = '"{}" -m pip {}'.format(self.path_python, args) return cmd def cmd_admin_pip_action(self, event): self.d.lst_log.possize(self.d.lst_package) self.d.lst_log.step = 1 self.d.step = 1 self.cmd_home_action(None) return def cmd_close_action(self, event): self.d.close() return def cmd_home_action(self, event): self.d.txt_search.value = '' self._list() return def txt_search_key_released(self, event): if event.KeyCode == app.KEY['enter']: self.cmd_search_action(None) return if not self.d.txt_search.value.strip(): self.cmd_home_action(None) return @app.run_in_thread def _list(self): self._set_state('list') self.d.lst_log.visible = False self.d.lst_package.visible = True cmd = self._cmd_pip(' list --format=json') self.d.lst_package.clear() result = app.run(cmd, True) packages = app.json_loads(result) for p in packages: t = '{} - ({})'.format(p['name'], p['version']) self.d.lst_package.insert(t, 'ok.png') self.d.lst_package.select() self.d.txt_search.set_focus() return @app.run_in_thread def _search(self, value): self._set_state('search') line = '' cmd = self._cmd_pip(' search {}'.format(value)) self.d.lst_package.clear() for line in app.popen(cmd): parts = line.split(')') name = parts[0].strip() + ')' description = parts[-1].strip() parts = name.split('(') name_verify = parts[0].strip() package = '{} {}'.format(name, description) image = PACKAGES.get(name_verify, 'question.png') self.d.lst_package.insert(package, image) if line: self.d.lst_package.select() else: self.d.lst_package.insert(_('Not found...'), 'error.png', show=False) return def cmd_search_action(self, event): search = self.d.txt_search.value.strip() if not search: self.d.txt_search.set_focus() return self._search(search) return @app.run_in_thread def _install(self, value): self._set_state('install') self.d.lst_package.visible = False self.d.lst_log.visible = True line = '' name = value.split(' ')[0].strip() cmd = self._cmd_pip(' install --upgrade --user {}'.format(name)) self.d.lst_log.clear() for line in app.popen(cmd): if self.OK1 in line or self.OK2 in line: self.d.lst_log.insert(line, 'ok.png') else: self.d.lst_log.insert(line) return @app.catch_exception def lst_package_double_click(self, event): opt = 'install' if self._states['list']: opt = 'upgrade' name = self.d.lst_package.value msg = _('Do you want {}:\n\n{} ?').format(opt, name) if not app.question(msg, TITLE): return self._install(name) return @app.run_in_thread def _uninstall(self, value): self._set_state('install') self.d.lst_package.visible = False self.d.lst_log.visible = True line = '' name = value.split(' ')[0].strip() cmd = self._cmd_pip(' uninstall -y {}'.format(name)) self.d.lst_log.clear() for line in app.popen(cmd): if self.OK3 in line: self.d.lst_log.insert(line, 'ok.png') else: self.d.lst_log.insert(line) return def cmd_uninstall_action(self, event): if not self._states['list']: msg = _('Select installed package') app.warning(msg) return name = self.d.lst_package.value msg = _('Do you want uninstall:\n\n{} ?').format(name) if not app.question(msg): return self._uninstall(name) return @app.catch_exception def cmd_shell_action(self, name): if app.IS_WIN: cmd = '"{}"'.format(self.path_python) app.open_file(cmd) else: if app.DESKTOP == 'gnome': cmd = 'gnome-terminal -- {}' else: if app.IS_MAC: cmd = 'open "{}"' else: cmd = 'exec "{}"' cmd = cmd.format(self.path_python) app.run(cmd) return class ZAZPip(unohelper.Base, XJobExecutor): def __init__(self, ctx): self.ctx = ctx def trigger(self, args): dialog = self._create_dialog() dialog.open() return def _create_dialog(self): args= { 'Name': 'dialog', 'Title': 'Zaz-Pip', 'Width': 200, 'Height': 220, } dialog = app.create_dialog(args) dialog.id_extension = ID_EXTENSION dialog.events = Controllers(dialog) args = { 'Type': 'Label', 'Name': 'lbl_title', 'Label': app.NAME + ' v' + app.VERSION, 'Width': 100, 'Height': 15, 'Border': 1, 'Align': 1, 'VerticalAlign': 1, 'Step': 10, '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) label = app.run(cmd, True) args = { 'Type': 'Label', 'Name': 'lbl_python', 'Label': str(label), 'Width': 100, 'Height': 15, 'Border': 1, '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) label = app.run(cmd, True) exists_pip = True if not label: exists_pip = False label = _('PIP not installed') args = { 'Type': 'Label', 'Name': 'lbl_pip', 'Label': label, 'Width': 160, 'Height': 30, 'Border': 1, 'Align': 1, 'VerticalAlign': 1, 'Step': 10, 'MultiLine': True, } dialog.add_control(args) dialog.center(dialog.lbl_pip, y=45) args = { 'Type': 'Button', 'Name': 'cmd_admin_pip', 'Label': _('Admin PIP'), 'Width': 60, 'Height': 18, 'Step': 10, 'ImageURL': 'python.png', 'ImagePosition': 1, } dialog.add_control(args) dialog.center(dialog.cmd_admin_pip, y=80) args = { 'Type': 'Button', 'Name': 'cmd_install_pip', 'Label': _('Install PIP'), 'Width': 60, 'Height': 18, 'Step': 10, 'ImageURL': 'install.png', 'ImagePosition': 1, } dialog.add_control(args) dialog.center(dialog.cmd_install_pip, y=80) args = { 'Type': 'Link', 'Name': 'link_proyect', 'URL': 'https://gitlab.com/mauriciobaeza/', 'Label': 'https://gitlab.com/mauriciobaeza/', 'Border': 1, 'Width': 130, 'Height': 15, 'Align': 1, 'VerticalAlign': 1, 'Step': 10, } dialog.add_control(args) dialog.center(dialog.link_proyect, y=-5) args = { 'Type': 'Listbox', 'Name': 'lst_log', 'Width': 160, 'Height': 105, 'Step': 10, } dialog.add_control(args) dialog.center(dialog.lst_log, y=105) args = { 'Type': 'Label', 'Name': 'lbl_package', 'Label': _('Packages'), 'Width': 100, 'Height': 15, 'Border': 1, 'Align': 1, 'VerticalAlign': 1, 'Step': 1, } dialog.add_control(args) args = { 'Type': 'Text', 'Name': 'txt_search', 'Width': 180, 'Height': 12, 'Step': 1, 'Border': 0, } dialog.add_control(args) args = { 'Type': 'Listbox', 'Name': 'lst_package', 'Width': 180, 'Height': 128, 'Step': 1, } dialog.add_control(args) args = { 'Type': 'Button', 'Name': 'cmd_close', 'Label': _('~Close'), 'Width': 60, 'Height': 18, 'Step': 1, 'ImageURL': 'close.png', 'ImagePosition': 1, # ~ 'PushButtonType': 2, } dialog.add_control(args) dialog.center(dialog.cmd_close, y=-5) args = { 'Type': 'Button', 'Name': 'cmd_home', 'Width': 18, 'Height': 18, 'Step': 1, 'ImageURL': 'home.png', 'FocusOnClick': False, 'Y': 2, } dialog.add_control(args) args = { 'Type': 'Button', 'Name': 'cmd_search', 'Width': 18, 'Height': 18, 'Step': 1, 'ImageURL': 'search.png', 'FocusOnClick': False, 'Y': 2, } dialog.add_control(args) args = { 'Type': 'Button', 'Name': 'cmd_uninstall', 'Width': 18, 'Height': 18, 'Step': 1, 'ImageURL': 'uninstall.png', 'FocusOnClick': False, 'Y': 2, } dialog.add_control(args) args = { 'Type': 'Button', 'Name': 'cmd_shell', 'Width': 18, 'Height': 18, 'Step': 1, 'ImageURL': 'shell.png', 'FocusOnClick': False, 'Y': 2, } dialog.add_control(args) controls = (dialog.cmd_home, dialog.cmd_search, dialog.cmd_uninstall, dialog.cmd_shell) dialog.lbl_package.move(dialog.cmd_home) dialog.txt_search.move(dialog.lbl_package) dialog.lst_package.move(dialog.txt_search) dialog.lbl_package.center() dialog.lst_package.center() dialog.txt_search.center() dialog.center(controls) dialog.step = 10 dialog.cmd_install_pip.visible = not exists_pip dialog.cmd_admin_pip.visible = exists_pip dialog.lst_log.visible = False return dialog g_ImplementationHelper = unohelper.ImplementationHelper() g_ImplementationHelper.addImplementation(ZAZPip, ID_EXTENSION, SERVICE)