Merge branch 'master' into mwhudson/curtin-logging
This commit is contained in:
commit
d27367465f
|
@ -89,6 +89,8 @@ The {keytype} host key fingerprints is:
|
|||
|
||||
def host_key_info():
|
||||
fingerprints = host_key_fingerprints()
|
||||
if len(fingerprints) == 0:
|
||||
return []
|
||||
if len(fingerprints) == 1:
|
||||
[(keytype, fingerprint)] = fingerprints
|
||||
return single_host_key_tmpl.format(keytype=keytype, fingerprint=fingerprint)
|
||||
|
|
|
@ -100,7 +100,7 @@ class IdentityView(BaseView):
|
|||
]
|
||||
return Pile(buttons)
|
||||
|
||||
def cancel(self, button):
|
||||
def cancel(self, button=None):
|
||||
self.controller.cancel()
|
||||
|
||||
def done(self, button):
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
name: subiquity
|
||||
version: "0.0.35"
|
||||
summary: Ubuntu installer
|
||||
description: The Ubuntu server installer
|
||||
confinement: classic
|
||||
|
||||
apps:
|
||||
subiquity:
|
||||
command: usr/bin/subiquity
|
||||
console-conf:
|
||||
command: usr/bin/console-conf
|
||||
probert:
|
||||
command: bin/probert
|
||||
|
||||
parts:
|
||||
subiquity:
|
||||
plugin: python
|
||||
build-packages: [python-setuptools]
|
||||
stage-packages: [curtin]
|
||||
python-packages:
|
||||
- urwid
|
||||
- pyyaml
|
||||
- pyudev
|
||||
- attrs
|
||||
source: https://github.com/CanonicalLtd/subiquity.git
|
||||
source-branch: cyphermox/snap
|
||||
source-type: git
|
||||
wrappers:
|
||||
plugin: dump
|
||||
source: https://github.com/CanonicalLtd/subiquity.git
|
||||
source-type: git
|
||||
organize:
|
||||
'bin/console-conf-tui': usr/bin/console-conf
|
||||
'bin/subiquity-tui': usr/bin/subiquity
|
||||
snap:
|
||||
- usr/bin
|
||||
probert:
|
||||
plugin: python
|
||||
build-packages: [python-setuptools, libnl-3-dev, libnl-genl-3-dev, libnl-route-3-dev]
|
||||
source: https://github.com/CanonicalLtd/probert.git
|
||||
source-type: git
|
|
@ -16,7 +16,7 @@
|
|||
import logging
|
||||
import os
|
||||
|
||||
from subiquitycore.controller import BaseController, view
|
||||
from subiquitycore.controller import BaseController
|
||||
from subiquitycore.ui.dummy import DummyView
|
||||
from subiquitycore.ui.error import ErrorView
|
||||
|
||||
|
@ -48,7 +48,6 @@ class FilesystemController(BaseController):
|
|||
self.raid_model = RaidModel()
|
||||
self.model.probe() # probe before we complete
|
||||
|
||||
@view
|
||||
def default(self, reset=False):
|
||||
# FIXME: Is this the best way to zero out this list for a reset?
|
||||
if reset:
|
||||
|
@ -64,7 +63,6 @@ class FilesystemController(BaseController):
|
|||
def reset(self):
|
||||
log.info("Resetting Filesystem model")
|
||||
self.model.reset()
|
||||
self.view_stack = []
|
||||
self.default()
|
||||
|
||||
def cancel(self):
|
||||
|
@ -113,7 +111,6 @@ class FilesystemController(BaseController):
|
|||
self.signal.emit_signal('next-screen')
|
||||
|
||||
# Filesystem/Disk partition -----------------------------------------------
|
||||
@view
|
||||
def partition_disk(self, disk):
|
||||
log.debug("In disk partition view, using {} as the disk.".format(disk.path))
|
||||
title = ("Partition, format, and mount {}".format(disk.path))
|
||||
|
@ -125,7 +122,6 @@ class FilesystemController(BaseController):
|
|||
|
||||
self.ui.set_body(dp_view)
|
||||
|
||||
@view
|
||||
def add_disk_partition(self, disk):
|
||||
log.debug("Adding partition to {}".format(disk))
|
||||
footer = ("Select whole disk, or partition, to format and mount.")
|
||||
|
@ -166,9 +162,9 @@ class FilesystemController(BaseController):
|
|||
self.model.add_mount(fs, spec['mountpoint'])
|
||||
|
||||
log.info("Successfully added partition")
|
||||
self.prev_view()
|
||||
self.partition_disk(disk)
|
||||
|
||||
def add_format_handler(self, volume, spec):
|
||||
def add_format_handler(self, volume, spec, back):
|
||||
log.debug('add_format_handler')
|
||||
if spec['fstype'] is not None:
|
||||
fs = self.model.add_filesystem(volume, spec['fstype'])
|
||||
|
@ -178,7 +174,7 @@ class FilesystemController(BaseController):
|
|||
if fs is None:
|
||||
raise Exception("{} is not formatted".format(volume.path))
|
||||
self.model.add_mount(fs, spec['mountpoint'])
|
||||
self.prev_view()
|
||||
back()
|
||||
|
||||
def connect_iscsi_disk(self, *args, **kwargs):
|
||||
# title = ("Disk and filesystem setup")
|
||||
|
@ -199,7 +195,6 @@ class FilesystemController(BaseController):
|
|||
# self.signal))
|
||||
self.ui.set_body(DummyView(self.signal))
|
||||
|
||||
@view
|
||||
def create_volume_group(self, *args, **kwargs):
|
||||
title = ("Create Logical Volume Group (\"LVM2\") disk")
|
||||
footer = ("ENTER on a disk will show detailed "
|
||||
|
@ -210,7 +205,6 @@ class FilesystemController(BaseController):
|
|||
self.ui.set_footer(footer)
|
||||
self.ui.set_body(LVMVolumeGroupView(self.model, self.signal))
|
||||
|
||||
@view
|
||||
def create_raid(self, *args, **kwargs):
|
||||
title = ("Create software RAID (\"MD\") disk")
|
||||
footer = ("ENTER on a disk will show detailed "
|
||||
|
@ -224,7 +218,6 @@ class FilesystemController(BaseController):
|
|||
self.ui.set_body(RaidView(self.model,
|
||||
self.signal))
|
||||
|
||||
@view
|
||||
def create_bcache(self, *args, **kwargs):
|
||||
title = ("Create hierarchical storage (\"bcache\") disk")
|
||||
footer = ("ENTER on a disk will show detailed "
|
||||
|
@ -242,17 +235,15 @@ class FilesystemController(BaseController):
|
|||
self.model.add_raid_device(result)
|
||||
self.signal.prev_signal()
|
||||
|
||||
@view
|
||||
def format_entire(self, disk):
|
||||
log.debug("format_entire {}".format(disk))
|
||||
header = ("Format and/or mount {}".format(disk.path))
|
||||
footer = ("Format or mount whole disk.")
|
||||
self.ui.set_header(header)
|
||||
self.ui.set_footer(footer)
|
||||
afv_view = AddFormatView(self.model, self, disk)
|
||||
afv_view = AddFormatView(self.model, self, disk, lambda : self.partition_disk(disk))
|
||||
self.ui.set_body(afv_view)
|
||||
|
||||
@view
|
||||
def format_mount_partition(self, partition):
|
||||
log.debug("format_entire {}".format(partition))
|
||||
if partition.fs() is not None:
|
||||
|
@ -263,7 +254,7 @@ class FilesystemController(BaseController):
|
|||
footer = ("Format and mount partition.")
|
||||
self.ui.set_header(header)
|
||||
self.ui.set_footer(footer)
|
||||
afv_view = AddFormatView(self.model, self, partition)
|
||||
afv_view = AddFormatView(self.model, self, partition, self.default)
|
||||
self.ui.set_body(afv_view)
|
||||
|
||||
def show_disk_information_next(self, disk):
|
||||
|
|
|
@ -24,7 +24,7 @@ log = logging.getLogger("subiquity.curtin")
|
|||
|
||||
TMPDIR = '/tmp'
|
||||
CURTIN_SEARCH_PATH = ['/usr/local/curtin/bin', '/usr/bin']
|
||||
CURTIN_INSTALL_PATH = ['/media/root-ro', '/']
|
||||
CURTIN_INSTALL_PATH = ['/media/root-ro', '/rofs', '/']
|
||||
CURTIN_INSTALL_LOG = '/tmp/subiquity-curtin-install.log'
|
||||
CURTIN_POSTINSTALL_LOG = '/tmp/subiquity-curtin-postinstall.log'
|
||||
CONF_PREFIX = os.path.join(TMPDIR, 'subiquity-config-')
|
||||
|
@ -59,12 +59,16 @@ POST_INSTALL_CONFIG = {
|
|||
'write_files': {
|
||||
'postinst_metadata': {
|
||||
'path': 'var/lib/cloud/seed/nocloud-net/meta-data',
|
||||
'content': 'instance-id: inst-3011',
|
||||
'content': 'instance-id: inst-3011\n',
|
||||
},
|
||||
'postinst_userdata': {
|
||||
'path': 'var/lib/cloud/seed/nocloud-net/user-data',
|
||||
# 'content' gets filled in later
|
||||
},
|
||||
'postinst_enable_cloudinit': {
|
||||
'path': 'etc/cloud/ds-identify.cfg',
|
||||
'content': 'policy: enabled\n',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,10 +46,11 @@ class AddFormatForm(Form):
|
|||
|
||||
|
||||
class AddFormatView(BaseView):
|
||||
def __init__(self, model, controller, volume):
|
||||
def __init__(self, model, controller, volume, back):
|
||||
self.model = model
|
||||
self.controller = controller
|
||||
self.volume = volume
|
||||
self.back = back
|
||||
|
||||
self.form = AddFormatForm(model)
|
||||
if self.volume.fs() is not None:
|
||||
|
@ -71,8 +72,8 @@ class AddFormatView(BaseView):
|
|||
format_box = Padding.center_50(ListBox(body))
|
||||
super().__init__(format_box)
|
||||
|
||||
def cancel(self, button):
|
||||
self.controller.prev_view()
|
||||
def cancel(self, button=None):
|
||||
self.back()
|
||||
|
||||
def done(self, result):
|
||||
""" format spec
|
||||
|
@ -97,4 +98,4 @@ class AddFormatView(BaseView):
|
|||
result['fstype'] = None
|
||||
|
||||
log.debug("Add Format Result: {}".format(result))
|
||||
self.controller.add_format_handler(self.volume, result)
|
||||
self.controller.add_format_handler(self.volume, result, self.back)
|
||||
|
|
|
@ -20,11 +20,9 @@ configuration.
|
|||
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from urwid import connect_signal, Text
|
||||
|
||||
from subiquitycore.ui.container import Columns, ListBox
|
||||
from subiquitycore.ui.container import ListBox
|
||||
from subiquitycore.ui.form import (
|
||||
Form,
|
||||
FormField,
|
||||
|
@ -114,8 +112,8 @@ class AddPartitionView(BaseView):
|
|||
partition_box = Padding.center_50(ListBox(body))
|
||||
super().__init__(partition_box)
|
||||
|
||||
def cancel(self, button):
|
||||
self.controller.prev_view()
|
||||
def cancel(self, button=None):
|
||||
self.controller.partition_disk(self.disk)
|
||||
|
||||
def done(self, result):
|
||||
|
||||
|
|
|
@ -63,5 +63,5 @@ class DiskInfoView(BaseView):
|
|||
''' Return to FilesystemView '''
|
||||
self.controller.partition_disk(self.disk)
|
||||
|
||||
def cancel(self, button):
|
||||
def cancel(self, button=None):
|
||||
self.controller.partition_disk(self.disk)
|
||||
|
|
|
@ -150,7 +150,7 @@ class DiskPartitionView(BaseView):
|
|||
|
||||
def done(self, result):
|
||||
''' Return to FilesystemView '''
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
|
||||
def cancel(self, button):
|
||||
self.controller.prev_view()
|
||||
def cancel(self, button=None):
|
||||
self.controller.default()
|
||||
|
|
|
@ -203,7 +203,7 @@ class FilesystemView(BaseView):
|
|||
user_data=sig)))
|
||||
return Pile(opts)
|
||||
|
||||
def cancel(self, button):
|
||||
def cancel(self, button=None):
|
||||
self.controller.cancel()
|
||||
|
||||
def reset(self, button):
|
||||
|
|
|
@ -102,14 +102,13 @@ class IdentityView(BaseView):
|
|||
|
||||
self.form = IdentityForm()
|
||||
connect_signal(self.form, 'submit', self.done)
|
||||
connect_signal(self.form, 'cancel', self.cancel)
|
||||
|
||||
self.ssh_import_confirmed = True
|
||||
|
||||
body = [
|
||||
Padding.center_90(self.form.as_rows(self)),
|
||||
Padding.line_break(""),
|
||||
Padding.fixed_10(self.form.buttons),
|
||||
Padding.fixed_10(self.form.buttons[0]),
|
||||
]
|
||||
super().__init__(ListBox(body))
|
||||
|
||||
|
@ -136,6 +135,3 @@ class IdentityView(BaseView):
|
|||
|
||||
log.debug("User input: {}".format(result))
|
||||
self.controller.create_user(result)
|
||||
|
||||
def cancel(self, button):
|
||||
self.controller.cancel()
|
||||
|
|
|
@ -63,5 +63,5 @@ class InstallpathView(BaseView):
|
|||
def confirm(self, result, sig):
|
||||
self.signal.emit_signal(sig)
|
||||
|
||||
def cancel(self, button):
|
||||
def cancel(self, button=None):
|
||||
self.signal.emit_signal('prev-screen')
|
||||
|
|
|
@ -20,14 +20,6 @@ import os
|
|||
|
||||
log = logging.getLogger("subiquitycore.controller")
|
||||
|
||||
def view(func):
|
||||
n = func.__name__
|
||||
def f(self, *args, **kw):
|
||||
m = getattr(self, n)
|
||||
self.view_stack.append((m, args, kw))
|
||||
return func(self, *args, **kw)
|
||||
return f
|
||||
|
||||
|
||||
class BaseController(ABC):
|
||||
"""Base class for controllers."""
|
||||
|
@ -42,7 +34,6 @@ class BaseController(ABC):
|
|||
self.prober = common['prober']
|
||||
self.controllers = common['controllers']
|
||||
self.pool = common['pool']
|
||||
self.view_stack = []
|
||||
|
||||
def register_signals(self):
|
||||
"""Defines signals associated with controller from model."""
|
||||
|
@ -51,11 +42,6 @@ class BaseController(ABC):
|
|||
signals.append((sig, getattr(self, cb)))
|
||||
self.signal.connect_signals(signals)
|
||||
|
||||
def prev_view(self):
|
||||
self.view_stack.pop()
|
||||
meth, args, kw = self.view_stack.pop()
|
||||
meth(*args, **kw)
|
||||
|
||||
def run_in_bg(self, func, callback):
|
||||
"""Run func() in a thread and call callback on UI thread.
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ from subiquitycore.ui.views import (NetworkView,
|
|||
NetworkConfigureWLANView)
|
||||
from subiquitycore.ui.views.network import ApplyingConfigWidget
|
||||
from subiquitycore.ui.dummy import DummyView
|
||||
from subiquitycore.controller import BaseController, view
|
||||
from subiquitycore.controller import BaseController
|
||||
from subiquitycore.utils import run_command_start, run_command_summarize
|
||||
|
||||
log = logging.getLogger("subiquitycore.controller.network")
|
||||
|
@ -341,17 +341,9 @@ class NetworkController(BaseController):
|
|||
self.observer.wlan_listener.trigger_scan(dev.ifindex)
|
||||
|
||||
def cancel(self):
|
||||
if len(self.view_stack) <= 1:
|
||||
self.signal.emit_signal('prev-screen')
|
||||
else:
|
||||
self.prev_view()
|
||||
|
||||
def default(self):
|
||||
self.view_stack = []
|
||||
self.start()
|
||||
|
||||
@view
|
||||
def start(self):
|
||||
title = "Network connections"
|
||||
excerpt = ("Configure at least one interface this server can use to talk to "
|
||||
"other machines, and which preferably provides sufficient access for "
|
||||
|
@ -428,45 +420,37 @@ class NetworkController(BaseController):
|
|||
self.signal.emit_signal('network-config-written', self.netplan_path)
|
||||
self.signal.emit_signal('next-screen')
|
||||
|
||||
@view
|
||||
def set_default_v4_route(self):
|
||||
self.ui.set_header("Default route")
|
||||
self.ui.set_body(NetworkSetDefaultRouteView(self.model, socket.AF_INET, self))
|
||||
|
||||
@view
|
||||
def set_default_v6_route(self):
|
||||
self.ui.set_header("Default route")
|
||||
self.ui.set_body(NetworkSetDefaultRouteView(self.model, socket.AF_INET6, self))
|
||||
|
||||
@view
|
||||
def bond_interfaces(self):
|
||||
self.ui.set_header("Bond interfaces")
|
||||
self.ui.set_body(NetworkBondInterfacesView(self.model, self))
|
||||
|
||||
@view
|
||||
def network_configure_interface(self, iface):
|
||||
self.ui.set_header("Network interface {}".format(iface))
|
||||
self.ui.set_body(NetworkConfigureInterfaceView(self.model, self, iface))
|
||||
|
||||
@view
|
||||
def network_configure_ipv4_interface(self, iface):
|
||||
self.ui.set_header("Network interface {} manual IPv4 "
|
||||
"configuration".format(iface))
|
||||
self.ui.set_body(NetworkConfigureIPv4InterfaceView(self.model, self, iface))
|
||||
|
||||
@view
|
||||
def network_configure_wlan_interface(self, iface):
|
||||
self.ui.set_header("Network interface {} WIFI "
|
||||
"configuration".format(iface))
|
||||
self.ui.set_body(NetworkConfigureWLANView(self.model, self, iface))
|
||||
|
||||
@view
|
||||
def network_configure_ipv6_interface(self, iface):
|
||||
self.ui.set_header("Network interface {} manual IPv6 "
|
||||
"configuration".format(iface))
|
||||
self.ui.set_body(NetworkConfigureIPv6InterfaceView(self.model, self, iface))
|
||||
|
||||
@view
|
||||
def install_network_driver(self):
|
||||
self.ui.set_body(DummyView(self))
|
||||
|
||||
|
|
|
@ -243,11 +243,6 @@ class _HelpDisplay(WidgetWrap):
|
|||
self._closer = closer
|
||||
button = Color.button(PlainButton(label="Close", on_press=lambda btn:self._closer()))
|
||||
super().__init__(LineBox(Pile([Text(help_text), Padding.fixed_10(button)]), title="Help"))
|
||||
def keypress(self, size, key):
|
||||
if key == 'esc':
|
||||
self._closer()
|
||||
else:
|
||||
return super().keypress(size, key)
|
||||
|
||||
|
||||
class Help(WidgetWrap):
|
||||
|
|
|
@ -260,5 +260,5 @@ class NetworkView(BaseView):
|
|||
def done(self, result):
|
||||
self.controller.network_finish(self.model.render())
|
||||
|
||||
def cancel(self, button):
|
||||
def cancel(self, button=None):
|
||||
self.controller.cancel()
|
||||
|
|
|
@ -127,8 +127,8 @@ class NetworkBondInterfacesView(BaseView):
|
|||
return
|
||||
|
||||
log.debug('bond: successful bond creation')
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
|
||||
def cancel(self, button):
|
||||
log.debug('bond: button_cancel')
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
|
|
|
@ -115,7 +115,7 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
self.dev = self.model.get_netdev_by_name(self.dev.name)
|
||||
except KeyError:
|
||||
# The interface is gone
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
return
|
||||
if self.dev.type == 'wlan':
|
||||
self.wifi_info.contents = [ (obj, ('pack', None)) for obj in _build_wifi_info(self.dev) ]
|
||||
|
@ -155,5 +155,8 @@ class NetworkConfigureInterfaceView(BaseView):
|
|||
def show_ipv6_configuration(self, btn):
|
||||
self.controller.network_configure_ipv6_interface(self.dev.name)
|
||||
|
||||
def cancel(self):
|
||||
self.controller.default()
|
||||
|
||||
def done(self, result):
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
|
|
|
@ -146,8 +146,7 @@ class BaseNetworkConfigureManualView(BaseView):
|
|||
self.dev = self.model.get_netdev_by_name(self.dev.name)
|
||||
except KeyError:
|
||||
# The interface is gone
|
||||
self.controller.prev_view()
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
return
|
||||
|
||||
def _build_set_as_default_gw_button(self):
|
||||
|
@ -193,11 +192,11 @@ class BaseNetworkConfigureManualView(BaseView):
|
|||
self.dev.add_network(self.ip_version, result)
|
||||
|
||||
# return
|
||||
self.controller.prev_view()
|
||||
self.controller.network_configure_interface(self.dev.name)
|
||||
|
||||
def cancel(self, sender):
|
||||
def cancel(self, sender=None):
|
||||
self.model.default_gateway = None
|
||||
self.controller.prev_view()
|
||||
self.controller.network_configure_interface(self.dev.name)
|
||||
|
||||
class NetworkConfigureIPv4InterfaceView(BaseNetworkConfigureManualView):
|
||||
ip_version = 4
|
||||
|
|
|
@ -82,13 +82,6 @@ class NetworkConfigureWLANView(BaseView):
|
|||
self.orig_w = None
|
||||
super().__init__(ListBox(self.body))
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key == 'esc':
|
||||
if self.orig_w is not None:
|
||||
self.remove_overlay()
|
||||
return
|
||||
return super().keypress(size, key)
|
||||
|
||||
def show_ssid_list(self, sender):
|
||||
self.show_overlay(NetworkList(self, self.dev.actual_ssids))
|
||||
|
||||
|
@ -138,8 +131,7 @@ class NetworkConfigureWLANView(BaseView):
|
|||
self.dev = self.model.get_netdev_by_name(self.dev.name)
|
||||
except KeyError:
|
||||
# The interface is gone
|
||||
self.controller.prev_view()
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
return
|
||||
self.inputs.contents = [ (obj, ('pack', None)) for obj in self._build_iface_inputs() ]
|
||||
|
||||
|
@ -156,7 +148,7 @@ class NetworkConfigureWLANView(BaseView):
|
|||
else:
|
||||
psk = None
|
||||
self.dev.set_ssid_psk(ssid, psk)
|
||||
self.controller.prev_view()
|
||||
self.controller.network_configure_interface(self.dev.name)
|
||||
|
||||
def cancel(self, sender):
|
||||
self.controller.prev_view()
|
||||
def cancel(self, sender=None):
|
||||
self.controller.network_configure_interface(self.dev.name)
|
||||
|
|
|
@ -139,7 +139,7 @@ class NetworkSetDefaultRouteView(BaseView):
|
|||
except ValueError:
|
||||
# FIXME: raise UX error message
|
||||
pass
|
||||
self.controller.prev_view()
|
||||
self.controller.default()
|
||||
|
||||
def cancel(self, button):
|
||||
self.controller.prev_view()
|
||||
def cancel(self, button=None):
|
||||
self.controller.default()
|
||||
|
|
|
@ -68,9 +68,17 @@ def environment_check(check):
|
|||
for ftype, items in checks[check_type].items():
|
||||
for i in items:
|
||||
if not os.path.exists(i):
|
||||
if 'SNAP' in os.environ:
|
||||
log.warn("Adjusting path for snaps: {}".format(os.environ.get('SNAP')))
|
||||
i = os.environ.get('SNAP') + i
|
||||
if not os.path.exists(i):
|
||||
env_ok = False
|
||||
else:
|
||||
env_ok = False
|
||||
|
||||
if not env_ok:
|
||||
log.error('FAIL: {} is not found on the'
|
||||
' filesystem'.format(i))
|
||||
env_ok = False
|
||||
continue
|
||||
if check_map[ftype](i) is False:
|
||||
log.error('FAIL: {} is NOT of type: {}'.format(i, ftype))
|
||||
|
|
|
@ -22,6 +22,11 @@ from urwid import Overlay, WidgetWrap
|
|||
|
||||
|
||||
class BaseView(WidgetWrap):
|
||||
|
||||
def __init__(self, w):
|
||||
self.orig_w = None
|
||||
super().__init__(w)
|
||||
|
||||
def show_overlay(self, overlay_widget, **kw):
|
||||
self.orig_w = self._w
|
||||
args = dict(
|
||||
|
@ -38,12 +43,19 @@ class BaseView(WidgetWrap):
|
|||
self._w = self.orig_w
|
||||
self.orig_w = None
|
||||
|
||||
def cancel(self):
|
||||
pass
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key in ['ctrl x']:
|
||||
self.controller.signal.emit_signal('control-x-quit')
|
||||
return None
|
||||
key = super().keypress(size, key)
|
||||
if key == 'esc':
|
||||
self.controller.cancel()
|
||||
if self.orig_w is not None:
|
||||
self.remove_overlay()
|
||||
return None
|
||||
else:
|
||||
self.cancel()
|
||||
return None
|
||||
return key
|
||||
|
|
Loading…
Reference in New Issue