From 03a34fbeddbf08bbb58e1d28e81c40c8ab27f4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Thu, 1 Apr 2021 22:25:48 +0200 Subject: [PATCH] qvm-template-gui: improve displaying progress The final version of qvm-template does not display untrusted data, so it is safe to decode UTF-8. Specifically, this shows download progress bar done using tqdm library. For this to work, \r needs to be properly handled, as tqdm uses it to erase the current line to update progress status. Since QTextEdit does not support it natively, add a simple wrapper for this job. Alternatively, qvm-template could be modified to display machine-readable progress info that would be passed through QT progress widget, but it would basically duplicate the work already done by tqdm library. We might do this at some point, though. And also enlarge progress window default size, to avoid wrapping. --- qubesmanager/qvm_template_gui.py | 23 +++++++++++++++++++---- ui/templateinstallprogressdlg.ui | 4 ++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/qubesmanager/qvm_template_gui.py b/qubesmanager/qvm_template_gui.py index 5c5b78d..d4a8e2c 100644 --- a/qubesmanager/qvm_template_gui.py +++ b/qubesmanager/qvm_template_gui.py @@ -15,7 +15,7 @@ from . import utils #pylint: disable=invalid-name -BASE_CMD = ['qvm-template', '--enablerepo=*', '--yes', '--quiet'] +BASE_CMD = ['qvm-template', '--enablerepo=*', '--yes'] class Template(typing.NamedTuple): status: str @@ -291,6 +291,19 @@ class TemplateInstallProgressDialog( self.actions = actions self.buttonBox.hide() + @staticmethod + def _process_cr(text): + """Reduce lines replaced using CR character (\r)""" + while '\r' in text: + prefix, suffix = text.rsplit('\r', 1) + if '\n' in prefix: + prefix = prefix.rsplit('\n', 1)[0] + prefix += '\n' + else: + prefix = '' + text = prefix + suffix + return text + def install(self): async def coro(): self.actions.sort() @@ -313,12 +326,14 @@ class TemplateInstallProgressDialog( stderr=asyncio.subprocess.STDOUT, env=envs) #pylint: disable=cell-var-from-loop + status_text = '' while True: - line = await proc.stdout.readline() + line = await proc.stdout.read(100) if line == b'': break - line = line.decode('ASCII') - self.textEdit.append(line.rstrip()) + line = line.decode('UTF-8') + status_text = self._process_cr(status_text + line) + self.textEdit.setPlainText(status_text) if await proc.wait() != 0: self.buttonBox.show() self.progressBar.setMaximum(100) diff --git a/ui/templateinstallprogressdlg.ui b/ui/templateinstallprogressdlg.ui index 5cc7791..3f98082 100644 --- a/ui/templateinstallprogressdlg.ui +++ b/ui/templateinstallprogressdlg.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 840 + 260