Add basic implementation for third-party drivers GUI
[Michael Hudson Doyle] * Original patch [Olivier Gayot] * Make sure visible elements can be translated by using gettext _() construct. * Have GET /drivers provide the status of the checkbox (i.e. install drivers?) so we can restore the choice of the user when going back. * Store an object with an "install" boolean in the autoinstall schema ; instead of storing a boolean directly. Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
parent
d1d3f82be5
commit
2ec62051d4
|
@ -56,4 +56,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -32,5 +32,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
|
||||
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -35,3 +35,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -79,3 +79,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -66,3 +66,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -40,3 +40,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -107,3 +107,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -66,3 +66,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -39,5 +39,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
|
||||
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -39,5 +39,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
|
||||
|
||||
Drivers:
|
||||
install: no
|
||||
|
|
|
@ -31,5 +31,5 @@ SnapList:
|
|||
classic: false
|
||||
InstallProgress:
|
||||
reboot: yes
|
||||
|
||||
|
||||
Drivers:
|
||||
install: yes
|
||||
|
|
|
@ -113,6 +113,7 @@ class SubiquityClient(TuiApplication):
|
|||
"Identity",
|
||||
"UbuntuAdvantage",
|
||||
"SSH",
|
||||
"Drivers",
|
||||
"SnapList",
|
||||
"Progress",
|
||||
]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from subiquitycore.tuicontroller import RepeatedController
|
||||
from .drivers import DriversController
|
||||
from .filesystem import FilesystemController
|
||||
from .identity import IdentityController
|
||||
from .keyboard import KeyboardController
|
||||
|
@ -32,6 +33,7 @@ from .zdev import ZdevController
|
|||
|
||||
# see SubiquityClient.controllers for another list
|
||||
__all__ = [
|
||||
'DriversController',
|
||||
'FilesystemController',
|
||||
'IdentityController',
|
||||
'KeyboardController',
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from subiquitycore.tuicontroller import Skip
|
||||
|
||||
from subiquity.common.types import DriversPayload, DriversResponse
|
||||
from subiquity.client.controller import SubiquityTuiController
|
||||
from subiquity.ui.views.drivers import DriversView
|
||||
|
||||
log = logging.getLogger('subiquity.client.controllers.drivers')
|
||||
|
||||
|
||||
class DriversController(SubiquityTuiController):
|
||||
|
||||
endpoint_name = 'drivers'
|
||||
|
||||
async def make_ui(self) -> DriversView:
|
||||
response: DriversResponse = await self.endpoint.GET()
|
||||
if response.drivers is not None and not response.drivers:
|
||||
raise Skip
|
||||
if response.drivers is None:
|
||||
return DriversView(self, None, response.install)
|
||||
else:
|
||||
return DriversView(self, bool(response.drivers), response.install)
|
||||
|
||||
async def _wait_drivers(self) -> bool:
|
||||
response: DriversResponse = await self.endpoint.GET(wait=True)
|
||||
assert response.drivers is not None
|
||||
return bool(response.drivers)
|
||||
|
||||
async def run_answers(self):
|
||||
if 'install' not in self.answers:
|
||||
return
|
||||
|
||||
import urwid
|
||||
from subiquitycore.testing.view_helpers import (
|
||||
click,
|
||||
find_button_matching,
|
||||
find_with_pred,
|
||||
)
|
||||
|
||||
def text_finder(txt):
|
||||
def pred(w):
|
||||
return isinstance(w, urwid.Text) and txt in w.text
|
||||
return pred
|
||||
|
||||
view = self.app.ui.body
|
||||
while find_with_pred(view, text_finder('Looking for')):
|
||||
await asyncio.sleep(0.2)
|
||||
if find_with_pred(view, text_finder('No applicable')):
|
||||
click(find_button_matching(view, "Continue"))
|
||||
return
|
||||
|
||||
view.form.install.value = self.answers['install']
|
||||
|
||||
click(view.form.done_btn)
|
||||
|
||||
def cancel(self):
|
||||
self.app.prev_screen()
|
||||
|
||||
def done(self, install):
|
||||
log.debug("DriversController.done next_screen install=%s", install)
|
||||
self.app.next_screen(
|
||||
self.endpoint.POST(DriversPayload(install=install)))
|
|
@ -0,0 +1,108 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" Install Path
|
||||
|
||||
Provides high level options for Ubuntu install
|
||||
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from urwid import (
|
||||
connect_signal,
|
||||
Text,
|
||||
)
|
||||
|
||||
from subiquitycore.ui.buttons import ok_btn
|
||||
from subiquitycore.ui.form import (
|
||||
Form,
|
||||
BooleanField,
|
||||
)
|
||||
from subiquitycore.ui.spinner import Spinner
|
||||
from subiquitycore.ui.utils import screen
|
||||
from subiquitycore.view import BaseView
|
||||
|
||||
|
||||
log = logging.getLogger('subiquity.ui.views.drivers')
|
||||
|
||||
|
||||
class DriversForm(Form):
|
||||
|
||||
cancel_label = _("Back")
|
||||
|
||||
install = BooleanField(_("Install the drivers?"))
|
||||
|
||||
|
||||
class DriversView(BaseView):
|
||||
|
||||
title = _("Third-party drivers.")
|
||||
|
||||
form = None
|
||||
|
||||
def __init__(self, controller, has_drivers: Optional[bool],
|
||||
install: bool) -> None:
|
||||
self.controller = controller
|
||||
|
||||
if has_drivers is None:
|
||||
self.make_waiting(install)
|
||||
else:
|
||||
self.make_main(install)
|
||||
|
||||
def make_waiting(self, install: bool):
|
||||
self.spinner = Spinner(self.controller.app.aio_loop, style='dots')
|
||||
self.spinner.start()
|
||||
rows = [
|
||||
Text(_("Looking for applicable third-party drivers...")),
|
||||
Text(""),
|
||||
self.spinner,
|
||||
]
|
||||
btn = ok_btn(_("Continue"), on_press=lambda sender: self.done(False))
|
||||
self._w = screen(rows, [btn])
|
||||
asyncio.create_task(self._wait(install))
|
||||
|
||||
async def _wait(self, install: bool):
|
||||
has_drivers = await self.controller._wait_drivers()
|
||||
self.spinner.stop()
|
||||
if has_drivers:
|
||||
self.make_main(install)
|
||||
else:
|
||||
self.make_no_drivers()
|
||||
|
||||
def make_no_drivers(self):
|
||||
rows = [Text(_("No applicable third-party drivers were found."))]
|
||||
btn = ok_btn(_("Continue"), on_press=lambda sender: self.done(False))
|
||||
self._w = screen(rows, [btn])
|
||||
|
||||
def make_main(self, install: bool) -> None:
|
||||
self.form = DriversForm(initial={'install': install})
|
||||
|
||||
excerpt = _(
|
||||
"Third-party drivers were found. Do you want to install them?")
|
||||
|
||||
connect_signal(
|
||||
self.form, 'submit',
|
||||
lambda result: self.done(result.install.value))
|
||||
connect_signal(self.form, 'cancel', self.cancel)
|
||||
|
||||
self._w = self.form.as_screen(excerpt=_(excerpt))
|
||||
|
||||
def done(self, result):
|
||||
log.debug("User input: %r", result)
|
||||
self.controller.done(result)
|
||||
|
||||
def cancel(self, result=None):
|
||||
self.controller.cancel()
|
Loading…
Reference in New Issue