start working on input validation
This commit is contained in:
parent
27131ef367
commit
0b3f3a5166
4 changed files with 200 additions and 7 deletions
|
@ -4,6 +4,7 @@ size and scale
|
|||
import tkinter as tk
|
||||
from tkinter import font, ttk
|
||||
|
||||
from coretk import validation
|
||||
from coretk.dialogs.dialog import Dialog
|
||||
|
||||
PAD = 5
|
||||
|
@ -37,6 +38,12 @@ class SizeAndScaleDialog(Dialog):
|
|||
self.meters_width = tk.IntVar(value=width / PIXEL_SCALE * location.scale)
|
||||
self.meters_height = tk.IntVar(value=height / PIXEL_SCALE * location.scale)
|
||||
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()
|
||||
|
||||
def draw(self):
|
||||
|
@ -47,6 +54,11 @@ class SizeAndScaleDialog(Dialog):
|
|||
self.draw_save_as_default()
|
||||
self.draw_buttons()
|
||||
|
||||
def focus_out(self, event):
|
||||
value = event.widget.get()
|
||||
if value == "":
|
||||
event.widget.insert(tk.END, 0)
|
||||
|
||||
def draw_size(self):
|
||||
label_frame = ttk.Labelframe(self.top, text="Size", padding=PAD)
|
||||
label_frame.grid(sticky="ew")
|
||||
|
@ -59,11 +71,22 @@ class SizeAndScaleDialog(Dialog):
|
|||
frame.columnconfigure(3, weight=1)
|
||||
label = ttk.Label(frame, text="Width")
|
||||
label.grid(row=0, column=0, sticky="w", padx=PAD)
|
||||
entry = ttk.Entry(frame, textvariable=self.pixel_width)
|
||||
entry = ttk.Entry(
|
||||
frame,
|
||||
textvariable=self.pixel_width,
|
||||
validate="key",
|
||||
validatecommand=(self.vcmd_canvas_int, "%P"),
|
||||
)
|
||||
entry.grid(row=0, column=1, sticky="ew", padx=PAD)
|
||||
entry.bind("<FocusOut>", self.focus_out)
|
||||
label = ttk.Label(frame, text="x Height")
|
||||
label.grid(row=0, column=2, sticky="w", padx=PAD)
|
||||
entry = ttk.Entry(frame, textvariable=self.pixel_height)
|
||||
entry = ttk.Entry(
|
||||
frame,
|
||||
textvariable=self.pixel_height,
|
||||
validate="key",
|
||||
validatecommand=(self.vcmd_canvas_int, "%P"),
|
||||
)
|
||||
entry.grid(row=0, column=3, sticky="ew", padx=PAD)
|
||||
label = ttk.Label(frame, text="Pixels")
|
||||
label.grid(row=0, column=4, sticky="w")
|
||||
|
@ -94,7 +117,12 @@ class SizeAndScaleDialog(Dialog):
|
|||
frame.columnconfigure(1, weight=1)
|
||||
label = ttk.Label(frame, text=f"{PIXEL_SCALE} Pixels =")
|
||||
label.grid(row=0, column=0, sticky="w", padx=PAD)
|
||||
entry = ttk.Entry(frame, textvariable=self.scale)
|
||||
entry = ttk.Entry(
|
||||
frame,
|
||||
textvariable=self.scale,
|
||||
validate="key",
|
||||
validatecommand=(self.vcmd_canvas_float, "%P"),
|
||||
)
|
||||
entry.grid(row=0, column=1, sticky="ew", padx=PAD)
|
||||
label = ttk.Label(frame, text="Meters")
|
||||
label.grid(row=0, column=2, sticky="w")
|
||||
|
|
|
@ -3,6 +3,7 @@ import tkinter as tk
|
|||
from functools import partial
|
||||
from tkinter import ttk
|
||||
|
||||
import coretk.validation as validation
|
||||
from coretk.dialogs.dialog import Dialog
|
||||
from coretk.dialogs.icondialog import IconDialog
|
||||
from coretk.dialogs.nodeservice import NodeService
|
||||
|
@ -69,7 +70,10 @@ class NodeConfigDialog(Dialog):
|
|||
# name field
|
||||
label = ttk.Label(frame, text="Name")
|
||||
label.grid(row=row, column=0, sticky="ew", padx=PAD, pady=PAD)
|
||||
entry = ttk.Entry(frame, textvariable=self.name)
|
||||
vcmd = self.app.master.register(validation.check_node_name)
|
||||
entry = ttk.Entry(
|
||||
frame, textvariable=self.name, validate="key", validatecommand=(vcmd, "%P")
|
||||
)
|
||||
entry.grid(row=row, column=1, sticky="ew")
|
||||
row += 1
|
||||
|
||||
|
@ -206,5 +210,4 @@ class NodeConfigDialog(Dialog):
|
|||
|
||||
# redraw
|
||||
self.canvas_node.redraw()
|
||||
|
||||
self.destroy()
|
||||
|
|
|
@ -1,3 +1,151 @@
|
|||
"""
|
||||
input validation
|
||||
"""
|
||||
import logging
|
||||
import tkinter as tk
|
||||
|
||||
|
||||
def validate_command(master, func):
|
||||
return master.register(func)
|
||||
|
||||
|
||||
def check_positive_int(s):
|
||||
logging.debug("int validation...")
|
||||
try:
|
||||
int_value = int(s)
|
||||
if int_value >= 0:
|
||||
return True
|
||||
return False
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def check_positive_float(s):
|
||||
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 True
|
||||
|
||||
|
||||
def check_canvas_int(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_canvas_float(s):
|
||||
logging.debug("canvas float validation")
|
||||
if not s:
|
||||
return True
|
||||
try:
|
||||
float_value = float(s)
|
||||
if float_value >= 0.0:
|
||||
return True
|
||||
return False
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def check_interface(name):
|
||||
logging.debug("interface name validation...")
|
||||
if len(name) <= 0:
|
||||
return False, "Interface name cannot be an empty string"
|
||||
for char in name:
|
||||
if not char.isalnum() and char != "_":
|
||||
return (
|
||||
False,
|
||||
"Interface name can only contain alphanumeric letter (a-z) and (0-9) or underscores (_)",
|
||||
)
|
||||
return True, ""
|
||||
|
||||
|
||||
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
|
||||
|
|
|
@ -5,6 +5,7 @@ from tkinter import font, ttk
|
|||
from tkinter.scrolledtext import ScrolledText
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from coretk import validation
|
||||
|
||||
INT_TYPES = {
|
||||
core_pb2.ConfigOptionType.UINT8,
|
||||
|
@ -60,6 +61,7 @@ class FrameScroll(ttk.LabelFrame):
|
|||
class ConfigFrame(FrameScroll):
|
||||
def __init__(self, master, app, config, **kw):
|
||||
super().__init__(master, app, ttk.Notebook, **kw)
|
||||
self.app = app
|
||||
self.config = config
|
||||
self.values = {}
|
||||
|
||||
|
@ -67,6 +69,8 @@ class ConfigFrame(FrameScroll):
|
|||
padx = 2
|
||||
pady = 2
|
||||
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:
|
||||
option = self.config[key]
|
||||
group = group_mapping.setdefault(option.group, [])
|
||||
|
@ -104,11 +108,21 @@ class ConfigFrame(FrameScroll):
|
|||
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||
elif option.type in INT_TYPES:
|
||||
value.set(option.value)
|
||||
entry = ttk.Entry(frame, textvariable=value)
|
||||
entry = ttk.Entry(
|
||||
frame,
|
||||
textvariable=value,
|
||||
validate="key",
|
||||
validatecommand=(vcmd_int, "%P"),
|
||||
)
|
||||
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||
elif option.type == core_pb2.ConfigOptionType.FLOAT:
|
||||
value.set(option.value)
|
||||
entry = ttk.Entry(frame, textvariable=value)
|
||||
entry = ttk.Entry(
|
||||
frame,
|
||||
textvariable=value,
|
||||
validate="key",
|
||||
validatecommand=(vcmd_float, "%P"),
|
||||
)
|
||||
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||
else:
|
||||
logging.error("unhandled config option type: %s", option.type)
|
||||
|
|
Loading…
Reference in a new issue