make the base controller have no ui, add subclass for one that has ui

This commit is contained in:
Michael Hudson-Doyle 2020-07-31 12:14:51 +12:00
parent f6757af8d1
commit edc65dbbfb
27 changed files with 187 additions and 157 deletions

View File

@ -20,12 +20,12 @@ from console_conf.ui.views import (
ChooserConfirmView, ChooserConfirmView,
) )
from subiquitycore.controller import BaseController from subiquitycore.tuicontroller import TuiController
log = logging.getLogger("console_conf.controllers.chooser") log = logging.getLogger("console_conf.controllers.chooser")
class RecoveryChooserBaseController(BaseController): class RecoveryChooserBaseController(TuiController):
def __init__(self, app): def __init__(self, app):
super().__init__(app) super().__init__(app)

View File

@ -20,9 +20,9 @@ import pwd
import shlex import shlex
import sys import sys
from subiquitycore.controller import BaseController
from subiquitycore.ssh import host_key_info, get_ips_standalone from subiquitycore.ssh import host_key_info, get_ips_standalone
from subiquitycore.snapd import SnapdConnection from subiquitycore.snapd import SnapdConnection
from subiquitycore.tuicontroller import TuiController
from subiquitycore.utils import disable_console_conf, run_command from subiquitycore.utils import disable_console_conf, run_command
from console_conf.ui.views import IdentityView, LoginView from console_conf.ui.views import IdentityView, LoginView
@ -141,7 +141,7 @@ def write_login_details_standalone():
return 0 return 0
class IdentityController(BaseController): class IdentityController(TuiController):
def __init__(self, app): def __init__(self, app):
super().__init__(app) super().__init__(app)

View File

@ -15,10 +15,10 @@
from console_conf.ui.views import WelcomeView, ChooserWelcomeView from console_conf.ui.views import WelcomeView, ChooserWelcomeView
from subiquitycore.controller import BaseController from subiquitycore.tuicontroller import TuiController
class WelcomeController(BaseController): class WelcomeController(TuiController):
welcome_view = WelcomeView welcome_view = WelcomeView

View File

@ -20,8 +20,10 @@ import jsonschema
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquitycore.controller import ( from subiquitycore.controller import (
BaseController, BaseController,
)
from subiquitycore.tuicontroller import (
RepeatedController, RepeatedController,
Skip, TuiController,
) )
log = logging.getLogger("subiquity.controller") log = logging.getLogger("subiquity.controller")
@ -39,6 +41,9 @@ class SubiquityController(BaseController):
self.context.set('controller', self) self.context.set('controller', self)
self.setup_autoinstall() self.setup_autoinstall()
def interactive(self):
return False
def setup_autoinstall(self): def setup_autoinstall(self):
if self.app.autoinstall_config: if self.app.autoinstall_config:
with self.context.child("load_autoinstall_data"): with self.context.child("load_autoinstall_data"):
@ -68,15 +73,6 @@ class SubiquityController(BaseController):
""" """
pass pass
def interactive(self):
if not self.app.autoinstall_config:
return True
i_sections = self.app.autoinstall_config.get(
'interactive-sections', [])
if '*' in i_sections or self.autoinstall_key in i_sections:
return True
return False
def configured(self): def configured(self):
"""Let the world know that this controller's model is now configured. """Let the world know that this controller's model is now configured.
""" """
@ -90,15 +86,15 @@ class SubiquityController(BaseController):
return {} return {}
class NoUIController(SubiquityController): class SubiquityTuiController(SubiquityController, TuiController):
def start_ui(self):
raise Skip
def cancel(self):
pass
def interactive(self): def interactive(self):
if not self.app.autoinstall_config:
return True
i_sections = self.app.autoinstall_config.get(
'interactive-sections', [])
if '*' in i_sections or self.autoinstall_key in i_sections:
return True
return False return False

View File

@ -18,10 +18,10 @@ import os
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquitycore.utils import arun_command from subiquitycore.utils import arun_command
from subiquity.controller import NoUIController from subiquity.controller import SubiquityController
class CmdListController(NoUIController): class CmdListController(SubiquityController):
autoinstall_default = [] autoinstall_default = []
autoinstall_schema = { autoinstall_schema = {

View File

@ -13,10 +13,10 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from subiquity.controller import NoUIController from subiquity.controller import SubiquityController
class DebconfController(NoUIController): class DebconfController(SubiquityController):
model_name = "debconf_selections" model_name = "debconf_selections"
autoinstall_key = "debconf-selections" autoinstall_key = "debconf-selections"

View File

@ -34,7 +34,7 @@ from subiquitycore.utils import (
from subiquity.common.errorreport import ErrorReportKind from subiquity.common.errorreport import ErrorReportKind
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.models.filesystem import ( from subiquity.models.filesystem import (
align_up, align_up,
Bootloader, Bootloader,
@ -61,7 +61,7 @@ PREP_GRUB_SIZE_BYTES = 8 * 1024 * 1024 # 8MiB
UEFI_GRUB_SIZE_BYTES = 512 * 1024 * 1024 # 512MiB EFI partition UEFI_GRUB_SIZE_BYTES = 512 * 1024 * 1024 # 512MiB EFI partition
class FilesystemController(SubiquityController): class FilesystemController(SubiquityTuiController):
autoinstall_key = "storage" autoinstall_key = "storage"
autoinstall_schema = {'type': 'object'} # ... autoinstall_schema = {'type': 'object'} # ...

View File

@ -19,13 +19,13 @@ import attr
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.ui.views import IdentityView from subiquity.ui.views import IdentityView
log = logging.getLogger('subiquity.controllers.identity') log = logging.getLogger('subiquity.controllers.identity')
class IdentityController(SubiquityController): class IdentityController(SubiquityTuiController):
autoinstall_key = model_name = "identity" autoinstall_key = model_name = "identity"
autoinstall_schema = { autoinstall_schema = {

View File

@ -44,7 +44,7 @@ from subiquitycore.utils import (
) )
from subiquity.common.errorreport import ErrorReportKind from subiquity.common.errorreport import ErrorReportKind
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.journald import journald_listener from subiquity.journald import journald_listener
from subiquity.ui.views.installprogress import ProgressView from subiquity.ui.views.installprogress import ProgressView
@ -78,7 +78,7 @@ class TracebackExtractor:
self.traceback.append(line) self.traceback.append(line)
class InstallProgressController(SubiquityController): class InstallProgressController(SubiquityTuiController):
def __init__(self, app): def __init__(self, app):
super().__init__(app) super().__init__(app)

View File

@ -20,14 +20,14 @@ import attr
from subiquitycore.async_helpers import schedule_task from subiquitycore.async_helpers import schedule_task
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.models.keyboard import KeyboardSetting from subiquity.models.keyboard import KeyboardSetting
from subiquity.ui.views import KeyboardView from subiquity.ui.views import KeyboardView
log = logging.getLogger('subiquity.controllers.keyboard') log = logging.getLogger('subiquity.controllers.keyboard')
class KeyboardController(SubiquityController): class KeyboardController(SubiquityTuiController):
autoinstall_key = model_name = "keyboard" autoinstall_key = model_name = "keyboard"
autoinstall_schema = { autoinstall_schema = {

View File

@ -27,7 +27,7 @@ from subiquitycore.async_helpers import (
) )
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.ui.views.mirror import MirrorView from subiquity.ui.views.mirror import MirrorView
log = logging.getLogger('subiquity.controllers.mirror') log = logging.getLogger('subiquity.controllers.mirror')
@ -40,7 +40,7 @@ class CheckState(enum.IntEnum):
DONE = enum.auto() DONE = enum.auto()
class MirrorController(SubiquityController): class MirrorController(SubiquityTuiController):
autoinstall_key = "apt" autoinstall_key = "apt"
autoinstall_schema = { # This is obviously incomplete. autoinstall_schema = { # This is obviously incomplete.

View File

@ -21,7 +21,7 @@ from subiquitycore.context import with_context
from subiquitycore.controllers.network import NetworkController from subiquitycore.controllers.network import NetworkController
from subiquity.common.errorreport import ErrorReportKind from subiquity.common.errorreport import ErrorReportKind
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
log = logging.getLogger("subiquity.controllers.network") log = logging.getLogger("subiquity.controllers.network")
@ -65,7 +65,7 @@ NETPLAN_SCHEMA = {
} }
class NetworkController(NetworkController, SubiquityController): class NetworkController(NetworkController, SubiquityTuiController):
ai_data = None ai_data = None
autoinstall_key = "network" autoinstall_key = "network"

View File

@ -13,10 +13,10 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from subiquity.controller import NoUIController from subiquity.controller import SubiquityController
class PackageController(NoUIController): class PackageController(SubiquityController):
model_name = autoinstall_key = "packages" model_name = autoinstall_key = "packages"
autoinstall_default = [] autoinstall_default = []

View File

@ -18,13 +18,13 @@ import os
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.ui.views.proxy import ProxyView from subiquity.ui.views.proxy import ProxyView
log = logging.getLogger('subiquity.controllers.proxy') log = logging.getLogger('subiquity.controllers.proxy')
class ProxyController(SubiquityController): class ProxyController(SubiquityTuiController):
autoinstall_key = model_name = "proxy" autoinstall_key = model_name = "proxy"
autoinstall_schema = { autoinstall_schema = {

View File

@ -22,12 +22,12 @@ from subiquitycore.async_helpers import schedule_task
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquitycore.utils import arun_command, run_command from subiquitycore.utils import arun_command, run_command
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
log = logging.getLogger("subiquity.controllers.restart") log = logging.getLogger("subiquity.controllers.restart")
class RebootController(SubiquityController): class RebootController(SubiquityTuiController):
def __init__(self, app): def __init__(self, app):
super().__init__(app) super().__init__(app)

View File

@ -25,12 +25,12 @@ from subiquitycore.async_helpers import (
SingleInstanceTask, SingleInstanceTask,
) )
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquitycore.controller import ( from subiquitycore.tuicontroller import (
Skip, Skip,
) )
from subiquity.controller import ( from subiquity.controller import (
SubiquityController, SubiquityTuiController,
) )
@ -43,7 +43,7 @@ class CheckState(enum.IntEnum):
UNAVAILABLE = enum.auto() UNAVAILABLE = enum.auto()
class RefreshController(SubiquityController): class RefreshController(SubiquityTuiController):
autoinstall_key = "refresh-installer" autoinstall_key = "refresh-installer"
autoinstall_schema = { autoinstall_schema = {

View File

@ -29,7 +29,7 @@ from curtin.reporter.handlers import (
LogHandler, LogHandler,
) )
from subiquity.controller import NoUIController from subiquity.controller import SubiquityController
class LogHandler(LogHandler): class LogHandler(LogHandler):
@ -46,7 +46,7 @@ INITIAL_CONFIG = {'logging': {'type': 'log'}}
NON_INTERACTIVE_CONFIG = {'builtin': {'type': 'print'}} NON_INTERACTIVE_CONFIG = {'builtin': {'type': 'print'}}
class ReportingController(NoUIController): class ReportingController(SubiquityController):
autoinstall_key = "reporting" autoinstall_key = "reporting"
autoinstall_schema = { autoinstall_schema = {

View File

@ -21,12 +21,12 @@ from subiquitycore.async_helpers import (
schedule_task, schedule_task,
) )
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquitycore.controller import ( from subiquitycore.tuicontroller import (
Skip, Skip,
) )
from subiquity.controller import ( from subiquity.controller import (
SubiquityController, SubiquityTuiController,
) )
from subiquity.models.snaplist import SnapSelection from subiquity.models.snaplist import SnapSelection
@ -104,7 +104,7 @@ class SnapdSnapInfoLoader:
return self.tasks[snap] return self.tasks[snap]
class SnapListController(SubiquityController): class SnapListController(SubiquityTuiController):
autoinstall_key = "snaps" autoinstall_key = "snaps"
autoinstall_default = [] autoinstall_default = []

View File

@ -20,7 +20,7 @@ from subiquitycore.async_helpers import schedule_task
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquitycore import utils from subiquitycore import utils
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.ui.views.ssh import SSHView from subiquity.ui.views.ssh import SSHView
log = logging.getLogger('subiquity.controllers.ssh') log = logging.getLogger('subiquity.controllers.ssh')
@ -32,7 +32,7 @@ class FetchSSHKeysFailure(Exception):
self.output = output self.output = output
class SSHController(SubiquityController): class SSHController(SubiquityTuiController):
autoinstall_key = model_name = "ssh" autoinstall_key = model_name = "ssh"
autoinstall_schema = { autoinstall_schema = {

View File

@ -13,10 +13,10 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from subiquity.controller import NoUIController from subiquity.controller import SubiquityController
class UserdataController(NoUIController): class UserdataController(SubiquityController):
model_name = 'userdata' model_name = 'userdata'
autoinstall_key = "user-data" autoinstall_key = "user-data"

View File

@ -18,14 +18,14 @@ import os
from subiquitycore.screen import is_linux_tty from subiquitycore.screen import is_linux_tty
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.ui.views import WelcomeView from subiquity.ui.views import WelcomeView
log = logging.getLogger('subiquity.controllers.welcome') log = logging.getLogger('subiquity.controllers.welcome')
class WelcomeController(SubiquityController): class WelcomeController(SubiquityTuiController):
autoinstall_key = model_name = "locale" autoinstall_key = model_name = "locale"
autoinstall_schema = {'type': 'string'} autoinstall_schema = {'type': 'string'}

View File

@ -24,7 +24,7 @@ from urwid import Text
from subiquitycore.ui.utils import Color from subiquitycore.ui.utils import Color
from subiquitycore.utils import run_command from subiquitycore.utils import run_command
from subiquity.controller import SubiquityController from subiquity.controller import SubiquityTuiController
from subiquity.ui.views import ZdevView from subiquity.ui.views import ZdevView
@ -631,7 +631,7 @@ class ZdevInfo:
return self.type return self.type
class ZdevController(SubiquityController): class ZdevController(SubiquityTuiController):
def __init__(self, app): def __init__(self, app):
super().__init__(app) super().__init__(app)

View File

@ -31,7 +31,7 @@ from subiquitycore.async_helpers import (
run_in_thread, run_in_thread,
schedule_task, schedule_task,
) )
from subiquitycore.controller import Skip from subiquitycore.tuicontroller import Skip
from subiquitycore.tui import TuiApplication from subiquitycore.tui import TuiApplication
from subiquitycore.snapd import ( from subiquitycore.snapd import (
AsyncSnapd, AsyncSnapd,

View File

@ -13,16 +13,12 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from abc import ABC, abstractmethod from abc import ABC
import logging import logging
log = logging.getLogger("subiquitycore.controller") log = logging.getLogger("subiquitycore.controller")
class Skip(Exception):
"""Raise this from a controller's start_ui method to skip a screen."""
class BaseController(ABC): class BaseController(ABC):
"""Base class for controllers.""" """Base class for controllers."""
@ -31,12 +27,10 @@ class BaseController(ABC):
def __init__(self, app): def __init__(self, app):
self.name = type(self).__name__[:-len("Controller")] self.name = type(self).__name__[:-len("Controller")]
self.ui = app.ui
self.signal = app.signal self.signal = app.signal
self.opts = app.opts self.opts = app.opts
self.app = app self.app = app
self.context = self.app.context.child(self.name, childlevel="DEBUG") self.context = self.app.context.child(self.name, childlevel="DEBUG")
self.answers = app.answers.get(self.name, {})
if self.model_name is not None: if self.model_name is not None:
self.model = getattr(self.app.base_model, self.model_name) self.model = getattr(self.app.base_model, self.model_name)
@ -57,92 +51,9 @@ class BaseController(ABC):
""" """
pass pass
@abstractmethod
def cancel(self):
pass
@property
def showing(self):
inst = self.app.controllers.cur
while isinstance(inst, RepeatedController):
inst = inst.orig
return inst is self
@abstractmethod
def start_ui(self):
"""Start running this controller's UI.
This method should call self.ui.set_body.
"""
def end_ui(self):
"""Stop running this controller's UI.
This method doesn't actually need to remove this controller's UI
as the next one is about to replace it, it's more of a hook to
stop any background tasks that can be stopped when the UI is not
running.
"""
def serialize(self): def serialize(self):
return None return None
def deserialize(self, data): def deserialize(self, data):
if data is not None: if data is not None:
raise Exception("missing deserialize method on {}".format(self)) raise Exception("missing deserialize method on {}".format(self))
# Stuff for fine grained actions, used by filesystem and network
# controller at time of writing this comment.
def _enter_form_data(self, form, data, submit, clean_suffix=''):
for k, v in data.items():
c = getattr(
self, '_action_clean_{}_{}'.format(k, clean_suffix), None)
if c is None:
c = getattr(self, '_action_clean_{}'.format(k), lambda x: x)
field = getattr(form, k)
from subiquitycore.ui.selector import Selector
v = c(v)
if isinstance(field.widget, Selector):
field.widget._emit('select', v)
field.value = v
yield
yield
for bf in form._fields:
bf.validate()
form.validated()
if submit:
if not form.done_btn.enabled:
raise Exception("answers left form invalid!")
form._click_done(None)
def _run_actions(self, actions):
for action in actions:
yield from self._answers_action(action)
def _run_iterator(self, it, delay=None):
if delay is None:
delay = 0.2/self.app.scale_factor
try:
next(it)
except StopIteration:
return
self.app.aio_loop.call_later(delay, self._run_iterator, it, delay/1.1)
class RepeatedController(BaseController):
def __init__(self, orig, index):
self.name = "{}-{}".format(orig.name, index)
self.orig = orig
self.index = index
self.context = orig.context
def register_signals(self):
pass
def start_ui(self):
self.orig.start_ui(self.index)
def cancel(self):
self.orig.cancel()

View File

@ -24,13 +24,13 @@ from probert.network import IFF_UP, NetworkEventReceiver
from subiquitycore.async_helpers import SingleInstanceTask from subiquitycore.async_helpers import SingleInstanceTask
from subiquitycore.context import with_context from subiquitycore.context import with_context
from subiquitycore.controller import BaseController
from subiquitycore.file_util import write_file from subiquitycore.file_util import write_file
from subiquitycore.models.network import ( from subiquitycore.models.network import (
BondParameters, BondParameters,
NetDevAction, NetDevAction,
) )
from subiquitycore import netplan from subiquitycore import netplan
from subiquitycore.tuicontroller import TuiController
from subiquitycore.ui.stretchy import StretchyOverlay from subiquitycore.ui.stretchy import StretchyOverlay
from subiquitycore.ui.views.network import ( from subiquitycore.ui.views.network import (
NetworkView, NetworkView,
@ -134,7 +134,7 @@ network:
''' '''
class NetworkController(BaseController): class NetworkController(TuiController):
model_name = "network" model_name = "network"
root = "/" root = "/"

View File

@ -20,13 +20,13 @@ import yaml
import urwid import urwid
from subiquitycore.async_helpers import schedule_task from subiquitycore.async_helpers import schedule_task
from subiquitycore.controller import Skip
from subiquitycore.core import Application from subiquitycore.core import Application
from subiquitycore.palette import ( from subiquitycore.palette import (
PALETTE_COLOR, PALETTE_COLOR,
PALETTE_MONO, PALETTE_MONO,
) )
from subiquitycore.screen import make_screen from subiquitycore.screen import make_screen
from subiquitycore.tuicontroller import Skip
from subiquitycore.ui.frame import SubiquityCoreUI from subiquitycore.ui.frame import SubiquityCoreUI
from subiquitycore.utils import arun_command from subiquitycore.utils import arun_command
@ -66,8 +66,8 @@ class TuiApplication(Application):
# Set rich_mode to the opposite of what we want, so we can # Set rich_mode to the opposite of what we want, so we can
# call toggle_rich to get the right things set up. # call toggle_rich to get the right things set up.
self.rich_mode = opts.run_on_serial self.rich_mode = opts.run_on_serial
self.urwid_loop = None self.urwid_loop = None
self.cur_screen = None
def _remove_last_screen(self): def _remove_last_screen(self):
last_screen = self.state_path('last-screen') last_screen = self.state_path('last-screen')
@ -102,6 +102,7 @@ class TuiApplication(Application):
raise Skip raise Skip
try: try:
new.start_ui() new.start_ui()
self.cur_screen = new
except Skip: except Skip:
new.context.exit("(skipped)") new.context.exit("(skipped)")
raise raise
@ -110,7 +111,7 @@ class TuiApplication(Application):
def _move_screen(self, increment): def _move_screen(self, increment):
self.save_state() self.save_state()
old = self.controllers.cur old, self.cur_screen = self.cur_screen, None
if old is not None: if old is not None:
old.context.exit("completed") old.context.exit("completed")
old.end_ui() old.end_ui()
@ -142,6 +143,8 @@ class TuiApplication(Application):
for controller in self.controllers.instances[:controller_index]: for controller in self.controllers.instances[:controller_index]:
controller.configured() controller.configured()
self.controllers.index = controller_index - 1 self.controllers.index = controller_index - 1
for controller in self.controllers.instances[:controller_index]:
controller.configured()
self.next_screen() self.next_screen()
def run_scripts(self, scripts): def run_scripts(self, scripts):

View File

@ -0,0 +1,120 @@
# Copyright 2020 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/>.
from abc import abstractmethod
import logging
from subiquitycore.controller import BaseController
log = logging.getLogger("subiquitycore.tuicontroller")
class Skip(Exception):
"""Raise this from a controller's start_ui method to skip a screen."""
class TuiController(BaseController):
"""Base class for controllers."""
def __init__(self, app):
super().__init__(app)
self.ui = app.ui
self.answers = app.answers.get(self.name, {})
@abstractmethod
def cancel(self):
pass
@property
def showing(self):
inst = self.app.controllers.cur
while isinstance(inst, RepeatedController):
inst = inst.orig
return inst is self
@abstractmethod
def start_ui(self):
"""Start running this controller's UI.
This method should call self.ui.set_body.
"""
def end_ui(self):
"""Stop running this controller's UI.
This method doesn't actually need to remove this controller's UI
as the next one is about to replace it, it's more of a hook to
stop any background tasks that can be stopped when the UI is not
running.
"""
# Stuff for fine grained actions, used by filesystem and network
# controller at time of writing this comment.
def _enter_form_data(self, form, data, submit, clean_suffix=''):
for k, v in data.items():
c = getattr(
self, '_action_clean_{}_{}'.format(k, clean_suffix), None)
if c is None:
c = getattr(self, '_action_clean_{}'.format(k), lambda x: x)
field = getattr(form, k)
from subiquitycore.ui.selector import Selector
v = c(v)
if isinstance(field.widget, Selector):
field.widget._emit('select', v)
field.value = v
yield
yield
for bf in form._fields:
bf.validate()
form.validated()
if submit:
if not form.done_btn.enabled:
raise Exception("answers left form invalid!")
form._click_done(None)
def _run_actions(self, actions):
for action in actions:
yield from self._answers_action(action)
def _run_iterator(self, it, delay=None):
if delay is None:
delay = 0.2/self.app.scale_factor
try:
next(it)
except StopIteration:
return
self.app.aio_loop.call_later(delay, self._run_iterator, it, delay/1.1)
class RepeatedController(BaseController):
def __init__(self, orig, index):
self.name = "{}-{}".format(orig.name, index)
self.orig = orig
self.index = index
self.context = orig.context
def register_signals(self):
pass
def start_ui(self):
self.orig.start_ui(self.index)
def end_ui(self):
self.orig.end_ui()
def cancel(self):
self.orig.cancel()