views: redraw screen after receiving event
Views that are dynamically updated using asynchronous events that are handled by urwid need to be redrawn. Ensure that such events trigger a redraw. Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
parent
e129c13590
commit
76815d6fa1
|
@ -585,14 +585,14 @@ class SubiquityClient(TuiApplication):
|
|||
else:
|
||||
super().unhandled_input(key)
|
||||
|
||||
def debug_shell(self, after_hook=None):
|
||||
async def debug_shell(self, after_hook=None):
|
||||
def _before():
|
||||
os.system("clear")
|
||||
print(DEBUG_SHELL_INTRO)
|
||||
|
||||
env = orig_environ(os.environ)
|
||||
cmd = ["bash"]
|
||||
self.run_command_in_foreground(
|
||||
await self.run_command_in_foreground(
|
||||
cmd, env=env, before_hook=_before, after_hook=after_hook, cwd="/"
|
||||
)
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ class FilesystemController(SubiquityTuiController, FilesystemManipulator):
|
|||
self.current_view = await self.make_guided_ui(status)
|
||||
if isinstance(self.ui.body, SlowProbing):
|
||||
self.ui.set_body(self.current_view)
|
||||
await self.app.redraw_screen()
|
||||
else:
|
||||
log.debug("not refreshing the display. Current display is %r", self.ui.body)
|
||||
|
||||
|
@ -273,18 +274,31 @@ class FilesystemController(SubiquityTuiController, FilesystemManipulator):
|
|||
self.ui.set_body(FilesystemView(self.model, self))
|
||||
|
||||
def guided_choice(self, choice):
|
||||
run_bg_task(self._guided_choice(choice))
|
||||
async def show_guided_and_redraw():
|
||||
await self._guided_choice(choice)
|
||||
await self.app.redraw_screen()
|
||||
|
||||
run_bg_task(show_guided_and_redraw())
|
||||
|
||||
async def _guided(self):
|
||||
self.ui.set_body((await self.make_ui())())
|
||||
|
||||
def guided(self):
|
||||
run_bg_task(self._guided())
|
||||
async def guided_and_redraw():
|
||||
await self._guided()
|
||||
await self.app.redraw_screen()
|
||||
|
||||
run_bg_task(guided_and_redraw())
|
||||
|
||||
def reset(self, refresh_view):
|
||||
async def reset_and_redraw():
|
||||
await self._reset(refresh_view)
|
||||
await self.app.redraw_screen()
|
||||
|
||||
log.info("Resetting Filesystem model")
|
||||
self.app.ui.block_input = True
|
||||
run_bg_task(self._reset(refresh_view))
|
||||
|
||||
run_bg_task(reset_and_redraw())
|
||||
|
||||
async def _reset(self, refresh_view):
|
||||
status = await self.endpoint.reset.POST()
|
||||
|
|
|
@ -69,27 +69,34 @@ class NetworkController(SubiquityTuiController, NetworkAnswersMixin):
|
|||
if act == LinkAction.DEL:
|
||||
self.view.del_link(info)
|
||||
|
||||
self.view.request_redraw_if_visible()
|
||||
|
||||
async def route_watch_POST(self, has_default_route: bool) -> None:
|
||||
if self.view is not None:
|
||||
self.view.update_has_default_route(has_default_route)
|
||||
self.view.request_redraw_if_visible()
|
||||
|
||||
async def apply_starting_POST(self) -> None:
|
||||
if self.view is not None:
|
||||
self.view.show_apply_spinner()
|
||||
self.view.request_redraw_if_visible()
|
||||
|
||||
async def apply_stopping_POST(self) -> None:
|
||||
if self.view is not None:
|
||||
self.view.hide_apply_spinner()
|
||||
self.view.request_redraw_if_visible()
|
||||
|
||||
async def apply_error_POST(self, stage: str) -> None:
|
||||
if self.view is not None:
|
||||
self.view.show_network_error(stage)
|
||||
self.view.request_redraw_if_visible()
|
||||
|
||||
async def wlan_support_install_finished_POST(
|
||||
self, state: PackageInstallState
|
||||
) -> None:
|
||||
if self.view:
|
||||
self.view.update_for_wlan_support_install_state(state.name)
|
||||
self.view.request_redraw_if_visible()
|
||||
|
||||
async def subscribe(self):
|
||||
self.tdir = tempfile.mkdtemp()
|
||||
|
|
|
@ -100,6 +100,7 @@ class SSHController(SubiquityTuiController):
|
|||
self.ui.body.fetching_ssh_keys_failed(
|
||||
_("Importing keys failed:"), response.error
|
||||
)
|
||||
self.ui.body.request_redraw()
|
||||
return
|
||||
elif response.status == SSHFetchIdStatus.FINGERPRINT_ERROR:
|
||||
if isinstance(self.ui.body, SSHView):
|
||||
|
@ -107,12 +108,14 @@ class SSHController(SubiquityTuiController):
|
|||
_("ssh-keygen failed to show fingerprint of downloaded keys:"),
|
||||
response.error,
|
||||
)
|
||||
self.ui.body.request_redraw()
|
||||
return
|
||||
|
||||
identities = response.identities
|
||||
|
||||
if isinstance(self.ui.body, SSHView):
|
||||
self.ui.body.confirm_ssh_keys(ssh_import_id, identities)
|
||||
self.ui.body.request_redraw()
|
||||
else:
|
||||
log.debug("ui.body of unexpected instance: %s", type(self.ui.body).__name__)
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ class DriversView(BaseView):
|
|||
self.make_main(install, drivers)
|
||||
else:
|
||||
self.make_no_drivers()
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
def make_no_drivers(self) -> None:
|
||||
"""Change the view into an information page that shows that no
|
||||
|
|
|
@ -336,15 +336,24 @@ class ErrorReportStretchy(Stretchy):
|
|||
if self.pile.selectable():
|
||||
while not self.pile.focus.selectable():
|
||||
self.pile.focus_position += 1
|
||||
await self.app.redraw_screen()
|
||||
|
||||
def debug_shell(self, sender):
|
||||
self.app.debug_shell()
|
||||
async def debug_shell_and_redraw():
|
||||
await self.app.debug_shell()
|
||||
await self.app.redraw_screen()
|
||||
|
||||
run_bg_task(debug_shell_and_redraw())
|
||||
|
||||
def restart(self, sender):
|
||||
self.app.restart(restart_server=True)
|
||||
|
||||
def view_report(self, sender):
|
||||
self.app.run_command_in_foreground(["less", self.report.path])
|
||||
async def run_less_and_redraw():
|
||||
await self.app.run_command_in_foreground(["less", self.report.path])
|
||||
await self.app.redraw_screen()
|
||||
|
||||
run_bg_task(run_less_and_redraw())
|
||||
|
||||
def submit(self, sender):
|
||||
self.report.upload()
|
||||
|
|
|
@ -429,8 +429,12 @@ class HelpMenu(PopUpLauncher):
|
|||
self.open_pop_up()
|
||||
|
||||
def _open(self, sender):
|
||||
async def get_ssh_info_and_redraw():
|
||||
await self._get_ssh_info()
|
||||
await self.app.redraw_screen()
|
||||
|
||||
log.debug("open help menu")
|
||||
run_bg_task(self._get_ssh_info())
|
||||
run_bg_task(get_ssh_info_and_redraw())
|
||||
|
||||
def create_pop_up(self):
|
||||
self._menu = OpenHelpMenu(self)
|
||||
|
@ -505,7 +509,11 @@ class HelpMenu(PopUpLauncher):
|
|||
self._show_overlay(GlobalKeyStretchy(self.app))
|
||||
|
||||
def debug_shell(self, sender):
|
||||
self.app.debug_shell()
|
||||
async def debug_shell_and_redraw():
|
||||
await self.app.debug_shell()
|
||||
await self.app.redraw_screen()
|
||||
|
||||
run_bg_task(debug_shell_and_redraw())
|
||||
|
||||
def toggle_rich(self, sender):
|
||||
self.app.toggle_rich()
|
||||
|
|
|
@ -101,6 +101,7 @@ class ProgressView(BaseView):
|
|||
)
|
||||
self.ongoing[context_id] = len(walker)
|
||||
self._add_line(self.event_listbox, new_line)
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
def event_finish(self, context_id):
|
||||
index = self.ongoing.pop(context_id, None)
|
||||
|
@ -110,6 +111,7 @@ class ProgressView(BaseView):
|
|||
spinner = walker[index][1]
|
||||
spinner.stop()
|
||||
walker[index] = walker[index][0]
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
def event_other(self, message: str, event_type: str) -> None:
|
||||
"""Print events that aren't start or finish events"""
|
||||
|
|
|
@ -270,8 +270,12 @@ class Detector:
|
|||
self.do_step(step_index)
|
||||
|
||||
def do_step(self, step_index):
|
||||
async def do_step_and_redraw():
|
||||
await self._do_step(step_index)
|
||||
self.keyboard_view.request_redraw_if_visible()
|
||||
|
||||
self.abort()
|
||||
run_bg_task(self._do_step(step_index))
|
||||
run_bg_task(do_step_and_redraw())
|
||||
|
||||
async def _do_step(self, step_index):
|
||||
log.debug("moving to step %s", step_index)
|
||||
|
@ -433,6 +437,7 @@ class KeyboardView(BaseView):
|
|||
)
|
||||
if needs_toggle:
|
||||
self.show_stretchy_overlay(ToggleQuestion(self, setting))
|
||||
self.request_redraw_if_visible()
|
||||
else:
|
||||
self.really_done(setting)
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ class MirrorView(BaseView):
|
|||
await asyncio.sleep(1 / self.controller.app.scale_factor)
|
||||
status = await self.controller.endpoint.check_mirror.progress.GET()
|
||||
self.update_status(status)
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
if check_state.status == MirrorCheckStatus.FAILED:
|
||||
self.output_wrap._w = Pile(
|
||||
|
|
|
@ -262,6 +262,7 @@ class RefreshView(BaseView):
|
|||
self.update_failed(err)
|
||||
return
|
||||
self.update_progress(change)
|
||||
self.request_redraw_if_visible()
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
def try_update_again(self, sender=None):
|
||||
|
|
|
@ -350,7 +350,12 @@ class SnapCheckBox(CheckBox):
|
|||
|
||||
def keypress(self, size, key):
|
||||
if key.startswith("enter"):
|
||||
schedule_task(self.load_info())
|
||||
|
||||
async def load_info_and_redraw():
|
||||
await self.load_info()
|
||||
self.parent.request_redraw_if_visible()
|
||||
|
||||
schedule_task(load_info_and_redraw())
|
||||
else:
|
||||
return super().keypress(size, key)
|
||||
|
||||
|
@ -379,6 +384,10 @@ class SnapListView(BaseView):
|
|||
self.loaded(data)
|
||||
|
||||
def wait_load(self):
|
||||
async def wait_load_and_redraw():
|
||||
await self._wait_load(spinner)
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
spinner = Spinner(style="dots")
|
||||
spinner.start()
|
||||
self._w = screen(
|
||||
|
@ -386,7 +395,7 @@ class SnapListView(BaseView):
|
|||
[ok_btn(label=_("Continue"), on_press=self.done)],
|
||||
excerpt=_("Loading server snaps from store, please wait..."),
|
||||
)
|
||||
schedule_task(self._wait_load(spinner))
|
||||
schedule_task(wait_load_and_redraw())
|
||||
|
||||
async def _wait_load(self, spinner):
|
||||
# If we show the loading screen at all, we want to show it for
|
||||
|
|
|
@ -535,6 +535,7 @@ class UbuntuProView(BaseView):
|
|||
self.remove_overlay()
|
||||
widget = TokenAddedWidget(parent=self, on_continue=show_subscription)
|
||||
self.show_stretchy_overlay(widget)
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
def upgrade_mode_done(self, form: UpgradeModeForm) -> None:
|
||||
"""Open the loading dialog and asynchronously check if the token is
|
||||
|
@ -563,6 +564,7 @@ class UbuntuProView(BaseView):
|
|||
form.validated()
|
||||
elif status == UbuntuProCheckTokenStatus.UNKNOWN_ERROR:
|
||||
self.show_unknown_error()
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
token: str = form.with_contract_token_subform.value["token"]
|
||||
checking_token_overlay = CheckingContractToken(self)
|
||||
|
@ -580,6 +582,7 @@ class UbuntuProView(BaseView):
|
|||
self.controller.contract_selection_initiate(on_initiated=self.cs_initiated)
|
||||
|
||||
self.upgrade_mode_form.set_user_code(user_code)
|
||||
self.request_redraw_if_visible()
|
||||
self.controller.contract_selection_wait(
|
||||
on_contract_selected=self.on_contract_selected,
|
||||
on_timeout=reinitiate,
|
||||
|
|
|
@ -67,6 +67,7 @@ class ZdevList(WidgetWrap):
|
|||
self.parent.controller.chzdev(action, zdevinfo), "Updating..."
|
||||
)
|
||||
self.update(new_zdevinfos)
|
||||
self.parent.request_redraw_if_visible()
|
||||
|
||||
def zdev_action(self, sender, action, zdevinfo):
|
||||
run_bg_task(self._zdev_action(action, zdevinfo))
|
||||
|
|
|
@ -24,7 +24,7 @@ from typing import Callable, Optional, Union
|
|||
import urwid
|
||||
import yaml
|
||||
|
||||
from subiquitycore.async_helpers import run_bg_task, schedule_task
|
||||
from subiquitycore.async_helpers import run_bg_task
|
||||
from subiquitycore.core import Application
|
||||
from subiquitycore.palette import PALETTE_COLOR, PALETTE_MONO
|
||||
from subiquitycore.screen import make_screen
|
||||
|
@ -83,7 +83,9 @@ class TuiApplication(Application):
|
|||
self.cur_screen = None
|
||||
self.fg_proc = None
|
||||
|
||||
def run_command_in_foreground(self, cmd, before_hook=None, after_hook=None, **kw):
|
||||
async def run_command_in_foreground(
|
||||
self, cmd, before_hook=None, after_hook=None, **kw
|
||||
):
|
||||
if self.fg_proc is not None:
|
||||
raise Exception("cannot run two fg processes at once")
|
||||
screen = self.urwid_loop.screen
|
||||
|
@ -119,7 +121,8 @@ class TuiApplication(Application):
|
|||
urwid.emit_signal(screen, urwid.display_common.INPUT_DESCRIPTORS_CHANGED)
|
||||
if before_hook is not None:
|
||||
before_hook()
|
||||
schedule_task(_run())
|
||||
|
||||
await _run()
|
||||
|
||||
async def make_view_for_controller(
|
||||
self, new
|
||||
|
@ -193,7 +196,7 @@ class TuiApplication(Application):
|
|||
|
||||
async def show_load():
|
||||
nonlocal ld
|
||||
ld = LoadingDialog(self.ui.body, message, task_to_cancel)
|
||||
ld = LoadingDialog(self, message, task_to_cancel)
|
||||
self.ui.body.show_overlay(ld, width=ld.width)
|
||||
await self.redraw_screen()
|
||||
|
||||
|
|
|
@ -380,4 +380,4 @@ class LoadingDialog(WidgetWrap):
|
|||
self.task_to_cancel.cancel()
|
||||
self.closed = True
|
||||
self.spinner.stop()
|
||||
self.parent.remove_overlay()
|
||||
self.parent.ui.body.remove_overlay()
|
||||
|
|
|
@ -66,6 +66,8 @@ class NetworkDeviceTable(WidgetWrap):
|
|||
def __init__(self, parent, dev_info):
|
||||
self.parent = parent
|
||||
self.dev_info = dev_info
|
||||
self.dhcp_spinner = Spinner(align="left")
|
||||
self.dhcp_spinner.rate = 0.3
|
||||
super().__init__(self._create())
|
||||
|
||||
def _create(self):
|
||||
|
@ -163,10 +165,8 @@ class NetworkDeviceTable(WidgetWrap):
|
|||
if addrs:
|
||||
address_info.extend([(label, Text(addr)) for addr in addrs])
|
||||
elif dhcp_status.state == DHCPState.PENDING:
|
||||
s = Spinner(align="left")
|
||||
s.rate = 0.3
|
||||
s.start()
|
||||
address_info.append((label, s))
|
||||
self.dhcp_spinner.start()
|
||||
address_info.append((label, self.dhcp_spinner))
|
||||
elif dhcp_status.state == DHCPState.TIMED_OUT:
|
||||
address_info.append((label, Text(_("timed out"))))
|
||||
elif dhcp_status.state == DHCPState.RECONFIGURE:
|
||||
|
@ -301,6 +301,8 @@ class NetworkView(BaseView):
|
|||
self.wlan_support_install_state_showing = False
|
||||
self.error_showing = False
|
||||
|
||||
self.apply_spinner = Spinner()
|
||||
|
||||
self.update_for_wlan_support_install_state(wlan_support_install_state)
|
||||
|
||||
super().__init__(
|
||||
|
@ -319,6 +321,7 @@ class NetworkView(BaseView):
|
|||
stretchy = ViewInterfaceInfo(self, name, info)
|
||||
stretchy.attach_context(self.controller.context.child("INFO"))
|
||||
self.show_stretchy_overlay(stretchy)
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
def _action_INFO(self, name, dev_info):
|
||||
run_bg_task(self._show_INFO(dev_info.name))
|
||||
|
@ -361,14 +364,13 @@ class NetworkView(BaseView):
|
|||
)
|
||||
|
||||
def show_apply_spinner(self):
|
||||
s = Spinner()
|
||||
s.start()
|
||||
self.apply_spinner.start()
|
||||
c = TablePile(
|
||||
[
|
||||
TableRow(
|
||||
[
|
||||
Text(_("Applying changes")),
|
||||
s,
|
||||
self.apply_spinner,
|
||||
]
|
||||
),
|
||||
],
|
||||
|
@ -378,10 +380,12 @@ class NetworkView(BaseView):
|
|||
(c, self.bottom.options()),
|
||||
(Text(""), self.bottom.options()),
|
||||
]
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
def hide_apply_spinner(self):
|
||||
if len(self.bottom.contents) > 2:
|
||||
self.bottom.contents[0:2] = []
|
||||
self.request_redraw_if_visible()
|
||||
|
||||
def new_link(self, new_dev_info):
|
||||
log.debug(
|
||||
|
|
|
@ -60,6 +60,8 @@ class SummaryController(SubiquityTuiController):
|
|||
if self.app_state == ApplicationState.DONE:
|
||||
if self.answers.get("reboot", False):
|
||||
self.click_reboot()
|
||||
if self.summary_view:
|
||||
self.summary_view.request_redraw_if_visible()
|
||||
|
||||
async def make_ui(self):
|
||||
real_name = ""
|
||||
|
|
Loading…
Reference in New Issue