updated new gui to properly update modified addresses for nodes, added validation for ip4/ip6, fixed redrawing edge labels when node addresses change
This commit is contained in:
parent
4093b2244a
commit
0d4a86f10e
3 changed files with 94 additions and 7 deletions
|
@ -1,9 +1,11 @@
|
||||||
import logging
|
import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from tkinter import ttk
|
from tkinter import messagebox, ttk
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
|
||||||
from core.gui import nodeutils
|
from core.gui import nodeutils
|
||||||
from core.gui.appconfig import ICONS_PATH
|
from core.gui.appconfig import ICONS_PATH
|
||||||
from core.gui.dialogs.dialog import Dialog
|
from core.gui.dialogs.dialog import Dialog
|
||||||
|
@ -18,6 +20,58 @@ if TYPE_CHECKING:
|
||||||
from core.gui.graph.node import CanvasNode
|
from core.gui.graph.node import CanvasNode
|
||||||
|
|
||||||
|
|
||||||
|
def check_ip6(parent, name: str, value: str) -> bool:
|
||||||
|
title = f"IP6 Error for {name}"
|
||||||
|
if not value:
|
||||||
|
messagebox.showerror(title, "Empty Value", parent=parent)
|
||||||
|
return False
|
||||||
|
values = value.split("/")
|
||||||
|
if len(values) != 2:
|
||||||
|
messagebox.showerror(
|
||||||
|
title, "Must be in the format address/prefix", parent=parent
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
addr, mask = values
|
||||||
|
if not netaddr.valid_ipv6(addr):
|
||||||
|
messagebox.showerror(title, "Invalid IP6 address", parent=parent)
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
mask = int(mask)
|
||||||
|
if not (0 <= mask <= 128):
|
||||||
|
messagebox.showerror(title, "Mask must be between 0-128", parent=parent)
|
||||||
|
return False
|
||||||
|
except ValueError:
|
||||||
|
messagebox.showerror(title, "Invalid Mask", parent=parent)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def check_ip4(parent, name: str, value: str) -> bool:
|
||||||
|
title = f"IP4 Error for {name}"
|
||||||
|
if not value:
|
||||||
|
messagebox.showerror(title, "Empty Value", parent=parent)
|
||||||
|
return False
|
||||||
|
values = value.split("/")
|
||||||
|
if len(values) != 2:
|
||||||
|
messagebox.showerror(
|
||||||
|
title, "Must be in the format address/prefix", parent=parent
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
addr, mask = values
|
||||||
|
if not netaddr.valid_ipv4(addr):
|
||||||
|
messagebox.showerror(title, "Invalid IP4 address", parent=parent)
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
mask = int(mask)
|
||||||
|
if not (0 <= mask <= 32):
|
||||||
|
messagebox.showerror(title, "Mask must be between 0-32", parent=parent)
|
||||||
|
return False
|
||||||
|
except ValueError:
|
||||||
|
messagebox.showerror(title, "Invalid mask", parent=parent)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry):
|
def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry):
|
||||||
logging.info("mac auto clicked")
|
logging.info("mac auto clicked")
|
||||||
if is_auto.get():
|
if is_auto.get():
|
||||||
|
@ -203,7 +257,6 @@ class NodeConfigDialog(Dialog):
|
||||||
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
||||||
ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}")
|
ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}")
|
||||||
entry = ttk.Entry(tab, textvariable=ip4)
|
entry = ttk.Entry(tab, textvariable=ip4)
|
||||||
entry.bind("<FocusOut>", self.app.validation.ip_focus_out)
|
|
||||||
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
|
@ -211,7 +264,6 @@ class NodeConfigDialog(Dialog):
|
||||||
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
||||||
ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}")
|
ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}")
|
||||||
entry = ttk.Entry(tab, textvariable=ip6)
|
entry = ttk.Entry(tab, textvariable=ip6)
|
||||||
entry.bind("<FocusOut>", self.app.validation.ip_focus_out)
|
|
||||||
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
||||||
|
|
||||||
self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6)
|
self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6)
|
||||||
|
@ -240,6 +292,8 @@ class NodeConfigDialog(Dialog):
|
||||||
self.image_file = file_path
|
self.image_file = file_path
|
||||||
|
|
||||||
def config_apply(self):
|
def config_apply(self):
|
||||||
|
error = False
|
||||||
|
|
||||||
# update core node
|
# update core node
|
||||||
self.node.name = self.name.get()
|
self.node.name = self.name.get()
|
||||||
if NodeUtils.is_image_node(self.node.type):
|
if NodeUtils.is_image_node(self.node.type):
|
||||||
|
@ -255,9 +309,31 @@ class NodeConfigDialog(Dialog):
|
||||||
# update canvas node
|
# update canvas node
|
||||||
self.canvas_node.image = self.image
|
self.canvas_node.image = self.image
|
||||||
|
|
||||||
|
# update node interface data
|
||||||
|
for interface in self.canvas_node.interfaces:
|
||||||
|
data = self.interfaces[interface.id]
|
||||||
|
if check_ip4(self, interface.name, data.ip4.get()):
|
||||||
|
ip4, ip4mask = data.ip4.get().split("/")
|
||||||
|
interface.ip4 = ip4
|
||||||
|
interface.ip4mask = int(ip4mask)
|
||||||
|
else:
|
||||||
|
error = True
|
||||||
|
data.ip4.set(f"{interface.ip4}/{interface.ip4mask}")
|
||||||
|
break
|
||||||
|
if check_ip6(self, interface.name, data.ip6.get()):
|
||||||
|
ip6, ip6mask = data.ip6.get().split("/")
|
||||||
|
interface.ip6 = ip6
|
||||||
|
interface.ip6mask = int(ip6mask)
|
||||||
|
interface.mac = data.mac.get()
|
||||||
|
else:
|
||||||
|
error = True
|
||||||
|
data.ip6.set(f"{interface.ip6}/{interface.ip6mask}")
|
||||||
|
break
|
||||||
|
|
||||||
# redraw
|
# redraw
|
||||||
self.canvas_node.redraw()
|
if not error:
|
||||||
self.destroy()
|
self.canvas_node.redraw()
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
def interface_select(self, event: tk.Event):
|
def interface_select(self, event: tk.Event):
|
||||||
listbox = event.widget
|
listbox = event.widget
|
||||||
|
|
|
@ -107,8 +107,7 @@ class CanvasEdge:
|
||||||
y = (y1 + y2) / 2
|
y = (y1 + y2) / 2
|
||||||
return x, y
|
return x, y
|
||||||
|
|
||||||
def draw_labels(self):
|
def create_labels(self):
|
||||||
x1, y1, x2, y2 = self.get_coordinates()
|
|
||||||
label_one = None
|
label_one = None
|
||||||
if self.link.HasField("interface_one"):
|
if self.link.HasField("interface_one"):
|
||||||
label_one = (
|
label_one = (
|
||||||
|
@ -121,6 +120,11 @@ class CanvasEdge:
|
||||||
f"{self.link.interface_two.ip4}/{self.link.interface_two.ip4mask}\n"
|
f"{self.link.interface_two.ip4}/{self.link.interface_two.ip4mask}\n"
|
||||||
f"{self.link.interface_two.ip6}/{self.link.interface_two.ip6mask}\n"
|
f"{self.link.interface_two.ip6}/{self.link.interface_two.ip6mask}\n"
|
||||||
)
|
)
|
||||||
|
return label_one, label_two
|
||||||
|
|
||||||
|
def draw_labels(self):
|
||||||
|
x1, y1, x2, y2 = self.get_coordinates()
|
||||||
|
label_one, label_two = self.create_labels()
|
||||||
self.text_src = self.canvas.create_text(
|
self.text_src = self.canvas.create_text(
|
||||||
x1,
|
x1,
|
||||||
y1,
|
y1,
|
||||||
|
@ -138,6 +142,11 @@ class CanvasEdge:
|
||||||
tags=tags.LINK_INFO,
|
tags=tags.LINK_INFO,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def redraw(self):
|
||||||
|
label_one, label_two = self.create_labels()
|
||||||
|
self.canvas.itemconfig(self.text_src, text=label_one)
|
||||||
|
self.canvas.itemconfig(self.text_dst, text=label_two)
|
||||||
|
|
||||||
def update_labels(self):
|
def update_labels(self):
|
||||||
"""
|
"""
|
||||||
Move edge labels based on current position.
|
Move edge labels based on current position.
|
||||||
|
|
|
@ -107,6 +107,8 @@ class CanvasNode:
|
||||||
def redraw(self):
|
def redraw(self):
|
||||||
self.canvas.itemconfig(self.id, image=self.image)
|
self.canvas.itemconfig(self.id, image=self.image)
|
||||||
self.canvas.itemconfig(self.text_id, text=self.core_node.name)
|
self.canvas.itemconfig(self.text_id, text=self.core_node.name)
|
||||||
|
for edge in self.edges:
|
||||||
|
edge.redraw()
|
||||||
|
|
||||||
def _get_label_y(self):
|
def _get_label_y(self):
|
||||||
image_box = self.canvas.bbox(self.id)
|
image_box = self.canvas.bbox(self.id)
|
||||||
|
|
Loading…
Reference in a new issue