start to add validation to manual network view

This commit is contained in:
Michael Hudson-Doyle 2017-02-07 20:18:11 +13:00
parent cf532a6b60
commit 0627bfe9f4
2 changed files with 48 additions and 128 deletions

View File

@ -21,12 +21,13 @@ configuration.
"""
import logging
import re
from urwid import AttrMap, connect_signal, Text, WidgetDisable, WidgetWrap
from urwid import connect_signal, Text
from subiquitycore.ui.buttons import done_btn, cancel_btn
from subiquitycore.ui.container import Columns, ListBox, Pile
from subiquitycore.ui.utils import Padding, Color
from subiquitycore.ui.interactive import StringEditor, IntegerEditor, Selector
from subiquitycore.ui.validation import Toggleable, ValidatingWidgetSet
from subiquitycore.view import BaseView
from subiquity.models.filesystem import (_humanize_size,
@ -38,82 +39,6 @@ from subiquity.ui.mount import MountSelector
log = logging.getLogger('subiquity.ui.filesystem.add_partition')
class Toggleable(WidgetWrap):
def __init__(self, original, active_color):
self.original = original
self.active_color = active_color
self.enabled = False
self.enable()
def enable(self):
if not self.enabled:
self._w = AttrMap(self.original, self.active_color, self.active_color + ' focus')
self.enabled = True
def disable(self):
if self.enabled:
self._w = WidgetDisable(Color.info_minor(self.original))
self.enabled = False
class ValidatingWidgetSet(WidgetWrap):
signals = ['validated']
def __init__(self, captioned, decorated, input, validator):
self.captioned = captioned
self.decorated = decorated
self.input = input
self.validator = validator
self.in_error = False
super().__init__(Pile([captioned]))
def disable(self):
self.decorated.disable()
self.hide_error()
def enable(self):
self.decorated.enable()
self.validate()
def set_error(self, err_msg):
in_error = True
if isinstance(err_msg, tuple):
if len(err_msg) == 3:
color, err_msg, in_error = err_msg
else:
color, err_msg = err_msg
else:
color = 'info_error'
e = AttrMap(Text(err_msg, align="center"), color)
t = (e, self._w.options('pack'))
if len(self._w.contents) > 1:
self._w.contents[1] = t
else:
self._w.contents.append(t)
self.in_error = in_error
def hide_error(self):
if len(self._w.contents) > 1:
self._w.contents = self._w.contents[:1]
self.in_error = False
def has_error(self):
return self.in_error
def validate(self):
if self.validator is not None:
err = self.validator()
if err is None:
self.hide_error()
else:
self.set_error(err)
self._emit('validated')
def lost_focus(self):
self.validate()
def vws(caption, input, validator=None):
text = Text(caption, align="right")

View File

@ -16,13 +16,14 @@
import logging
import ipaddress
from urwid import Text
from urwid import connect_signal, Text
from subiquitycore.view import BaseView
from subiquitycore.ui.buttons import done_btn, menu_btn, cancel_btn
from subiquitycore.ui.container import Columns, ListBox, Pile
from subiquitycore.ui.utils import Color, Padding
from subiquitycore.ui.interactive import StringEditor
from subiquitycore.ui.utils import Color, Padding
from subiquitycore.ui.validation import Toggleable, ValidatingWidgetSet
log = logging.getLogger('subiquitycore.network.network_configure_ipv4_interface')
@ -52,6 +53,7 @@ class BaseNetworkConfigureManualView(BaseView):
self.searchdomains_input.value = ', '.join(self.dev.configured_searchdomains)
self.error = Text("", align='center')
#self.set_as_default_gw_button = Pile(self._build_set_as_default_gw_button())
self.buttons = self._build_buttons()
body = [
Padding.center_79(self._build_iface_inputs()),
#Padding.line_break(""),
@ -59,7 +61,7 @@ class BaseNetworkConfigureManualView(BaseView):
Padding.line_break(""),
Padding.center_90(Color.info_error(self.error)),
Padding.line_break(""),
Padding.fixed_10(self._build_buttons())
Padding.fixed_10(self.buttons)
]
super().__init__(ListBox(body))
@ -72,55 +74,48 @@ class BaseNetworkConfigureManualView(BaseView):
self.controller.prev_view()
return
def _vws(self, caption, input, help, validator=None):
text = Text(caption, align="right")
decorated = Toggleable(input, 'string_input')
captioned = Columns(
[
("weight", 0.2, text),
("weight", 0.3,
Color.string_input(input,
focus_map="string_input focus")),
("weight", 0.5, Text(help))
], dividechars=2
)
return ValidatingWidgetSet(captioned, decorated, input, validator)
def _build_iface_inputs(self):
col1 = [
Columns(
[
("weight", 0.2, Text("Subnet:")),
("weight", 0.3,
Color.string_input(self.subnet_input,
focus_map="string_input focus")),
("weight", 0.5, Text("CIDR e.g. %s"%(self.example_address,)))
], dividechars=2
),
Columns(
[
("weight", 0.2, Text("Address:")),
("weight", 0.3,
Color.string_input(self.address_input,
focus_map="string_input focus")),
("weight", 0.5, Text(""))
], dividechars=2
),
Columns(
[
("weight", 0.2, Text("Gateway:")),
("weight", 0.3,
Color.string_input(self.gateway_input,
focus_map="string_input focus")),
("weight", 0.5, Text(""))
], dividechars=2
),
Columns(
[
("weight", 0.2, Text("Name servers:")),
("weight", 0.3,
Color.string_input(self.nameserver_input,
focus_map="string_input focus")),
("weight", 0.5, Text("IP addresses, comma separated"))
], dividechars=2
),
Columns(
[
("weight", 0.2, Text("Search domains:")),
("weight", 0.3,
Color.string_input(self.searchdomains_input,
focus_map="string_input focus")),
("weight", 0.5, Text("Domains, comma separated"))
], dividechars=2
),
self.all_vws = [
self._vws("Subnet:", self.subnet_input, "CIDR e.g. %s"%(self.example_address,), self._validate_subnet),
self._vws("Address:", self.address_input, ""),
self._vws("Gateway:", self.gateway_input, ""),
self._vws("Name servers:", self.nameserver_input, "IP addresses, comma separated"),
self._vws("Search domains:", self.searchdomains_input, "Domains, comma separated"),
]
return Pile(col1)
for vw in self.all_vws:
connect_signal(vw, 'validated', self._validated)
return Pile(self.all_vws)
def _validate_subnet(self):
subnet = self.subnet_input.value
if '/' not in subnet:
return "should be in CIDR form (xx.xx.xx.xx/yy)"
def _validated(self, sender):
error = False
for w in self.all_vws:
if w.has_error():
error = True
break
if error:
self.buttons[0].disable()
self.buttons.focus_position = 1
else:
self.buttons[0].enable()
def _build_set_as_default_gw_button(self):
devs = self.model.get_all_netdevs()
@ -153,7 +148,7 @@ class BaseNetworkConfigureManualView(BaseView):
done = done_btn(on_press=self.done)
buttons = [
Color.button(done, focus_map='button focus'),
Toggleable(done, 'button'),
Color.button(cancel, focus_map='button focus')
]
return Pile(buttons)