add validation to canvassizescale, wlanconfig, nodename

This commit is contained in:
Huy Pham 2019-12-10 09:57:12 -08:00
parent 7039a3682e
commit ada21997e9
5 changed files with 140 additions and 165 deletions

View file

@ -12,6 +12,7 @@ from coretk.menubar import Menubar
from coretk.nodeutils import NodeUtils from coretk.nodeutils import NodeUtils
from coretk.statusbar import StatusBar from coretk.statusbar import StatusBar
from coretk.toolbar import Toolbar from coretk.toolbar import Toolbar
from coretk.validation import InputValidation
class Application(tk.Frame): class Application(tk.Frame):
@ -25,6 +26,7 @@ class Application(tk.Frame):
self.toolbar = None self.toolbar = None
self.canvas = None self.canvas = None
self.statusbar = None self.statusbar = None
self.validation = None
# setup # setup
self.guiconfig = appconfig.read() self.guiconfig = appconfig.read()
@ -48,6 +50,7 @@ class Application(tk.Frame):
image = Images.get(ImageEnum.CORE, 16) image = Images.get(ImageEnum.CORE, 16)
self.master.tk.call("wm", "iconphoto", self.master._w, image) self.master.tk.call("wm", "iconphoto", self.master._w, image)
self.pack(fill=tk.BOTH, expand=True) self.pack(fill=tk.BOTH, expand=True)
self.validation = InputValidation(self)
def center(self): def center(self):
width = 1000 width = 1000

View file

@ -4,7 +4,6 @@ size and scale
import tkinter as tk import tkinter as tk
from tkinter import font, ttk from tkinter import font, ttk
from coretk import validation
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
PAD = 5 PAD = 5
@ -20,6 +19,7 @@ class SizeAndScaleDialog(Dialog):
""" """
super().__init__(master, app, "Canvas Size and Scale", modal=True) super().__init__(master, app, "Canvas Size and Scale", modal=True)
self.canvas = self.app.canvas self.canvas = self.app.canvas
self.validation = app.validation
self.section_font = font.Font(weight="bold") self.section_font = font.Font(weight="bold")
# get current canvas dimensions # get current canvas dimensions
plot = self.canvas.find_withtag("rectangle") plot = self.canvas.find_withtag("rectangle")
@ -38,12 +38,6 @@ class SizeAndScaleDialog(Dialog):
self.meters_width = tk.IntVar(value=width / PIXEL_SCALE * location.scale) self.meters_width = tk.IntVar(value=width / PIXEL_SCALE * location.scale)
self.meters_height = tk.IntVar(value=height / PIXEL_SCALE * location.scale) self.meters_height = tk.IntVar(value=height / PIXEL_SCALE * location.scale)
self.save_default = tk.BooleanVar(value=False) self.save_default = tk.BooleanVar(value=False)
self.vcmd_canvas_int = validation.validate_command(
app.master, validation.check_canvas_int
)
self.vcmd_canvas_float = validation.validate_command(
app.master, validation.check_canvas_float
)
self.draw() self.draw()
def draw(self): def draw(self):
@ -54,11 +48,6 @@ class SizeAndScaleDialog(Dialog):
self.draw_save_as_default() self.draw_save_as_default()
self.draw_buttons() self.draw_buttons()
def focus_out(self, event):
value = event.widget.get()
if value == "":
event.widget.insert(tk.END, 0)
def draw_size(self): def draw_size(self):
label_frame = ttk.Labelframe(self.top, text="Size", padding=PAD) label_frame = ttk.Labelframe(self.top, text="Size", padding=PAD)
label_frame.grid(sticky="ew") label_frame.grid(sticky="ew")
@ -75,18 +64,19 @@ class SizeAndScaleDialog(Dialog):
frame, frame,
textvariable=self.pixel_width, textvariable=self.pixel_width,
validate="key", validate="key",
validatecommand=(self.vcmd_canvas_int, "%P"), validatecommand=(self.validation.positive_int, "%P"),
) )
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=1, sticky="ew", padx=PAD) entry.grid(row=0, column=1, sticky="ew", padx=PAD)
entry.bind("<FocusOut>", self.focus_out)
label = ttk.Label(frame, text="x Height") label = ttk.Label(frame, text="x Height")
label.grid(row=0, column=2, sticky="w", padx=PAD) label.grid(row=0, column=2, sticky="w", padx=PAD)
entry = ttk.Entry( entry = ttk.Entry(
frame, frame,
textvariable=self.pixel_height, textvariable=self.pixel_height,
validate="key", validate="key",
validatecommand=(self.vcmd_canvas_int, "%P"), validatecommand=(self.validation.positive_int, "%P"),
) )
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=3, sticky="ew", padx=PAD) entry.grid(row=0, column=3, sticky="ew", padx=PAD)
label = ttk.Label(frame, text="Pixels") label = ttk.Label(frame, text="Pixels")
label.grid(row=0, column=4, sticky="w") label.grid(row=0, column=4, sticky="w")
@ -98,11 +88,23 @@ class SizeAndScaleDialog(Dialog):
frame.columnconfigure(3, weight=1) frame.columnconfigure(3, weight=1)
label = ttk.Label(frame, text="Width") label = ttk.Label(frame, text="Width")
label.grid(row=0, column=0, sticky="w", padx=PAD) label.grid(row=0, column=0, sticky="w", padx=PAD)
entry = ttk.Entry(frame, textvariable=self.meters_width) entry = ttk.Entry(
frame,
textvariable=self.meters_width,
validate="key",
validatecommand=(self.validation.positive_float, "%P"),
)
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=1, sticky="ew", padx=PAD) entry.grid(row=0, column=1, sticky="ew", padx=PAD)
label = ttk.Label(frame, text="x Height") label = ttk.Label(frame, text="x Height")
label.grid(row=0, column=2, sticky="w", padx=PAD) label.grid(row=0, column=2, sticky="w", padx=PAD)
entry = ttk.Entry(frame, textvariable=self.meters_height) entry = ttk.Entry(
frame,
textvariable=self.meters_height,
validate="key",
validatecommand=(self.validation.positive_float, "%P"),
)
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=3, sticky="ew", padx=PAD) entry.grid(row=0, column=3, sticky="ew", padx=PAD)
label = ttk.Label(frame, text="Meters") label = ttk.Label(frame, text="Meters")
label.grid(row=0, column=4, sticky="w") label.grid(row=0, column=4, sticky="w")
@ -121,8 +123,9 @@ class SizeAndScaleDialog(Dialog):
frame, frame,
textvariable=self.scale, textvariable=self.scale,
validate="key", validate="key",
validatecommand=(self.vcmd_canvas_float, "%P"), validatecommand=(self.validation.positive_float, "%P"),
) )
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=1, sticky="ew", padx=PAD) entry.grid(row=0, column=1, sticky="ew", padx=PAD)
label = ttk.Label(frame, text="Meters") label = ttk.Label(frame, text="Meters")
label.grid(row=0, column=2, sticky="w") label.grid(row=0, column=2, sticky="w")
@ -144,12 +147,24 @@ class SizeAndScaleDialog(Dialog):
label = ttk.Label(frame, text="X") label = ttk.Label(frame, text="X")
label.grid(row=0, column=0, sticky="w", padx=PAD) label.grid(row=0, column=0, sticky="w", padx=PAD)
entry = ttk.Entry(frame, textvariable=self.x) entry = ttk.Entry(
frame,
textvariable=self.x,
validate="key",
validatecommand=(self.validation.positive_float, "%P"),
)
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=1, sticky="ew", padx=PAD) entry.grid(row=0, column=1, sticky="ew", padx=PAD)
label = ttk.Label(frame, text="Y") label = ttk.Label(frame, text="Y")
label.grid(row=0, column=2, sticky="w", padx=PAD) label.grid(row=0, column=2, sticky="w", padx=PAD)
entry = ttk.Entry(frame, textvariable=self.y) entry = ttk.Entry(
frame,
textvariable=self.y,
validate="key",
validatecommand=(self.validation.positive_float, "%P"),
)
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=3, sticky="ew", padx=PAD) entry.grid(row=0, column=3, sticky="ew", padx=PAD)
label = ttk.Label(label_frame, text="Translates To") label = ttk.Label(label_frame, text="Translates To")
@ -163,17 +178,35 @@ class SizeAndScaleDialog(Dialog):
label = ttk.Label(frame, text="Lat") label = ttk.Label(frame, text="Lat")
label.grid(row=0, column=0, sticky="w", padx=PAD) label.grid(row=0, column=0, sticky="w", padx=PAD)
entry = ttk.Entry(frame, textvariable=self.lat) entry = ttk.Entry(
frame,
textvariable=self.lat,
validate="key",
validatecommand=(self.validation.positive_float, "%P"),
)
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=1, sticky="ew", padx=PAD) entry.grid(row=0, column=1, sticky="ew", padx=PAD)
label = ttk.Label(frame, text="Lon") label = ttk.Label(frame, text="Lon")
label.grid(row=0, column=2, sticky="w", padx=PAD) label.grid(row=0, column=2, sticky="w", padx=PAD)
entry = ttk.Entry(frame, textvariable=self.lon) entry = ttk.Entry(
frame,
textvariable=self.lon,
validate="key",
validatecommand=(self.validation.positive_float, "%P"),
)
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=3, sticky="ew", padx=PAD) entry.grid(row=0, column=3, sticky="ew", padx=PAD)
label = ttk.Label(frame, text="Alt") label = ttk.Label(frame, text="Alt")
label.grid(row=0, column=4, sticky="w", padx=PAD) label.grid(row=0, column=4, sticky="w", padx=PAD)
entry = ttk.Entry(frame, textvariable=self.alt) entry = ttk.Entry(
frame,
textvariable=self.alt,
validate="key",
validatecommand=(self.validation.positive_float, "%P"),
)
entry.bind("<FocusOut>", self.validation.focus_out)
entry.grid(row=0, column=5, sticky="ew") entry.grid(row=0, column=5, sticky="ew")
def draw_save_as_default(self): def draw_save_as_default(self):

View file

@ -3,7 +3,6 @@ import tkinter as tk
from functools import partial from functools import partial
from tkinter import ttk from tkinter import ttk
import coretk.validation as validation
from coretk.dialogs.dialog import Dialog from coretk.dialogs.dialog import Dialog
from coretk.dialogs.icondialog import IconDialog from coretk.dialogs.icondialog import IconDialog
from coretk.dialogs.nodeservice import NodeService from coretk.dialogs.nodeservice import NodeService
@ -70,10 +69,13 @@ class NodeConfigDialog(Dialog):
# name field # name field
label = ttk.Label(frame, text="Name") label = ttk.Label(frame, text="Name")
label.grid(row=row, column=0, sticky="ew", padx=PAD, pady=PAD) label.grid(row=row, column=0, sticky="ew", padx=PAD, pady=PAD)
vcmd = self.app.master.register(validation.check_node_name)
entry = ttk.Entry( entry = ttk.Entry(
frame, textvariable=self.name, validate="key", validatecommand=(vcmd, "%P") frame,
textvariable=self.name,
validate="key",
validatecommand=(self.app.validation.name, "%P"),
) )
entry.bind("<FocusOut>", self.app.validation.name_focus_out)
entry.grid(row=row, column=1, sticky="ew") entry.grid(row=row, column=1, sticky="ew")
row += 1 row += 1

View file

@ -5,147 +5,85 @@ import logging
import tkinter as tk import tkinter as tk
def validate_command(master, func): class InputValidation:
return master.register(func) def __init__(self, app):
self.master = app.master
self.positive_int = None
self.positive_float = None
self.name = None
self.register()
def register(self):
self.positive_int = self.master.register(self.check_positive_int)
self.positive_float = self.master.register(self.check_positive_float)
self.name = self.master.register(self.check_node_name)
def check_positive_int(s): def focus_out(self, event):
logging.debug("int validation...") value = event.widget.get()
try: if value == "":
int_value = int(s) event.widget.insert(tk.END, 0)
if int_value >= 0:
def name_focus_out(self, event):
logging.debug("name focus out")
value = event.widget.get()
if value == "":
event.widget.insert(tk.END, "empty")
def check_positive_int(self, s):
logging.debug("int validation...")
if len(s) == 0:
return True return True
return False try:
except ValueError: int_value = int(s)
return False if int_value >= 0:
return True
return False
def check_positive_float(s): except ValueError:
logging.debug("float validation...")
try:
float_value = float(s)
if float_value >= 0.0:
return True
return False
except ValueError:
return False
def check_node_name(name):
logging.debug("node name validation...")
if len(name) <= 0:
return False
for char in name:
if not char.isalnum() and char != "_":
return False return False
return True
def check_positive_float(self, s):
def check_canvas_int(s): logging.debug("float validation...")
logging.debug("int validation...") if len(s) == 0:
if len(s) == 0:
return True
try:
int_value = int(s)
if int_value >= 0:
return True return True
return False try:
except ValueError: float_value = float(s)
return False if float_value >= 0.0:
return True
return False
except ValueError:
return False
def check_node_name(self, s):
def check_canvas_float(s): logging.debug("node name validation...")
logging.debug("canvas float validation") if len(s) < 0:
if not s: return False
return True if len(s) == 0:
try:
float_value = float(s)
if float_value >= 0.0:
return True return True
return False for char in s:
except ValueError: if not char.isalnum() and char != "_":
return False return False
return True
def check_canvas_int(sefl, s):
logging.debug("int validation...")
if len(s) == 0:
return True
try:
int_value = int(s)
if int_value >= 0:
return True
return False
except ValueError:
return False
def check_interface(name): def check_canvas_float(self, s):
logging.debug("interface name validation...") logging.debug("canvas float validation")
if len(name) <= 0: if not s:
return False, "Interface name cannot be an empty string" return True
for char in name: try:
if not char.isalnum() and char != "_": float_value = float(s)
return ( if float_value >= 0.0:
False, return True
"Interface name can only contain alphanumeric letter (a-z) and (0-9) or underscores (_)", return False
) except ValueError:
return True, "" return False
def combine_message(key, current_validation, current_message, res, msg):
if not res:
current_validation = res
current_message = current_message + key + ": " + msg + "\n\n"
return current_validation, current_message
def check_wlan_config(config):
result = True
message = ""
checks = ["bandwidth", "delay", "error", "jitter", "range"]
for check in checks:
if check in ["bandwidth", "delay", "jitter"]:
res, msg = check_positive_int(config[check].value)
result, message = combine_message(check, result, message, res, msg)
elif check in ["range", "error"]:
res, msg = check_positive_float(config[check].value)
result, message = combine_message(check, result, message, res, msg)
return result, message
def check_size_and_scale(dialog):
result = True
message = ""
try:
pixel_width = dialog.pixel_width.get()
if pixel_width < 0:
result, message = combine_message(
"pixel width", result, message, False, "cannot be negative"
)
except tk.TclError:
result, message = combine_message(
"pixel width",
result,
message,
False,
"invalid value, input non-negative float",
)
try:
pixel_height = dialog.pixel_height.get()
if pixel_height < 0:
result, message = combine_message(
"pixel height", result, message, False, "cannot be negative"
)
except tk.TclError:
result, message = combine_message(
"pixel height",
result,
message,
False,
"invalid value, input non-negative float",
)
try:
scale = dialog.scale.get()
if scale <= 0:
result, message = combine_message(
"scale", result, message, False, "cannot be negative"
)
except tk.TclError:
result, message = combine_message(
"scale", result, message, False, "invalid value, input non-negative float"
)
# pixel_height = dialog.pixel_height.get()
# print(pixel_width, pixel_height)
# res, msg = check_positive_int(pixel_width)
# result, message = combine_message("pixel width", result, message, res, msg)
# res, msg = check_positive_int(pixel_height)
# result, message = combine_message("pixel height", result, message, res, msg)
return result, message

View file

@ -5,7 +5,6 @@ from tkinter import filedialog, font, ttk
from tkinter.scrolledtext import ScrolledText from tkinter.scrolledtext import ScrolledText
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from coretk import validation
INT_TYPES = { INT_TYPES = {
core_pb2.ConfigOptionType.UINT8, core_pb2.ConfigOptionType.UINT8,
@ -75,8 +74,6 @@ class ConfigFrame(FrameScroll):
padx = 2 padx = 2
pady = 2 pady = 2
group_mapping = {} group_mapping = {}
vcmd_int = self.app.master.register(validation.check_positive_int)
vcmd_float = self.app.master.register(validation.check_positive_float)
for key in self.config: for key in self.config:
option = self.config[key] option = self.config[key]
group = group_mapping.setdefault(option.group, []) group = group_mapping.setdefault(option.group, [])
@ -128,8 +125,9 @@ class ConfigFrame(FrameScroll):
frame, frame,
textvariable=value, textvariable=value,
validate="key", validate="key",
validatecommand=(vcmd_int, "%P"), validatecommand=(self.app.validation.positive_int, "%P"),
) )
entry.bind("<FocusOut>", self.app.validation.focus_out)
entry.grid(row=index, column=1, sticky="ew", pady=pady) entry.grid(row=index, column=1, sticky="ew", pady=pady)
elif option.type == core_pb2.ConfigOptionType.FLOAT: elif option.type == core_pb2.ConfigOptionType.FLOAT:
value.set(option.value) value.set(option.value)
@ -137,8 +135,9 @@ class ConfigFrame(FrameScroll):
frame, frame,
textvariable=value, textvariable=value,
validate="key", validate="key",
validatecommand=(vcmd_float, "%P"), validatecommand=(self.app.validation.positive_float, "%P"),
) )
entry.bind("<FocusOut>", self.app.validation.focus_out)
entry.grid(row=index, column=1, sticky="ew", pady=pady) entry.grid(row=index, column=1, sticky="ew", pady=pady)
else: else:
logging.error("unhandled config option type: %s", option.type) logging.error("unhandled config option type: %s", option.type)