core-extra/daemon/core/gui/validation.py

124 lines
2.9 KiB
Python
Raw Normal View History

2019-12-09 18:07:21 +00:00
"""
input validation
"""
2019-12-11 00:50:28 +00:00
import re
2019-12-10 00:33:32 +00:00
import tkinter as tk
from tkinter import ttk
from typing import Any, Optional, Pattern
2020-01-14 19:06:52 +00:00
SMALLEST_SCALE: float = 0.5
LARGEST_SCALE: float = 5.0
HEX_REGEX: Pattern = re.compile("^([#]([0-9]|[a-f])+)$|^[#]$")
2019-12-10 00:33:32 +00:00
class ValidationEntry(ttk.Entry):
empty: Optional[str] = None
def __init__(
self,
master: tk.BaseWidget = None,
widget: tk.BaseWidget = None,
empty_enabled: bool = True,
**kwargs: Any
) -> None:
super().__init__(master, widget, **kwargs)
cmd = self.register(self.is_valid)
self.configure(validate="key", validatecommand=(cmd, "%P"))
if self.empty is not None and empty_enabled:
self.bind("<FocusOut>", self.focus_out)
def is_valid(self, s: str) -> bool:
raise NotImplementedError
def focus_out(self, _event: tk.Event) -> None:
value = self.get()
if not value:
self.insert(tk.END, self.empty)
class PositiveIntEntry(ValidationEntry):
empty: str = "0"
def is_valid(self, s: str) -> bool:
if not s:
2019-12-10 00:33:32 +00:00
return True
try:
value = int(s)
return value >= 0
except ValueError:
2019-12-10 00:33:32 +00:00
return False
class PositiveFloatEntry(ValidationEntry):
empty = "0.0"
def is_valid(self, s: str) -> bool:
if not s:
return True
try:
value = float(s)
return value >= 0.0
except ValueError:
return False
2019-12-10 00:33:32 +00:00
class FloatEntry(ValidationEntry):
empty = "0.0"
def is_valid(self, s: str) -> bool:
if not s:
return True
try:
float(s)
return True
except ValueError:
return False
2019-12-11 00:50:28 +00:00
class RgbEntry(ValidationEntry):
def is_valid(self, s: str) -> bool:
if not s:
return True
if s.startswith("0") and len(s) >= 2:
return False
try:
value = int(s)
return 0 <= value <= 255
except ValueError:
return False
class HexEntry(ValidationEntry):
def is_valid(self, s: str) -> bool:
2019-12-11 00:50:28 +00:00
if not s:
return True
if HEX_REGEX.match(s):
return 0 <= len(s) <= 7
2019-12-11 00:50:28 +00:00
else:
return False
2019-12-13 23:52:48 +00:00
class NodeNameEntry(ValidationEntry):
empty: str = "noname"
def is_valid(self, s: str) -> bool:
if len(s) < 0:
2019-12-13 23:52:48 +00:00
return False
if len(s) == 0:
return True
for x in s:
if not x.isalnum() and x != "_":
2019-12-13 23:52:48 +00:00
return False
return True
2019-12-13 23:52:48 +00:00
class AppScaleEntry(ValidationEntry):
def is_valid(self, s: str) -> bool:
2019-12-13 23:52:48 +00:00
if not s:
return True
try:
float_value = float(s)
return SMALLEST_SCALE <= float_value <= LARGEST_SCALE or float_value == 0
except ValueError:
2019-12-13 23:52:48 +00:00
return False