pygui: added type hinting to class variables for core.gui.dialogs
This commit is contained in:
parent
11be40bc90
commit
527d34e374
37 changed files with 664 additions and 613 deletions
|
@ -38,7 +38,7 @@ from core.api.grpc.mobility_pb2 import MobilityConfig
|
|||
from core.api.grpc.services_pb2 import NodeServiceData, ServiceConfig, ServiceFileConfig
|
||||
from core.api.grpc.wlan_pb2 import WlanConfig
|
||||
from core.gui import appconfig
|
||||
from core.gui.appconfig import CoreServer
|
||||
from core.gui.appconfig import CoreServer, Observer
|
||||
from core.gui.dialogs.emaneinstall import EmaneInstallDialog
|
||||
from core.gui.dialogs.error import ErrorDialog
|
||||
from core.gui.dialogs.mobilityplayer import MobilityPlayer
|
||||
|
@ -75,7 +75,7 @@ class CoreClient:
|
|||
# loaded configuration data
|
||||
self.servers: Dict[str, CoreServer] = {}
|
||||
self.custom_nodes: Dict[str, NodeDraw] = {}
|
||||
self.custom_observers: Dict[str, str] = {}
|
||||
self.custom_observers: Dict[str, Observer] = {}
|
||||
self.read_config()
|
||||
|
||||
# helpers
|
||||
|
|
|
@ -35,11 +35,11 @@ THE POSSIBILITY OF SUCH DAMAGE.\
|
|||
|
||||
|
||||
class AboutDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "About CORE")
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ check engine light
|
|||
"""
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
from core.api.grpc.core_pb2 import ExceptionLevel
|
||||
from core.api.grpc.core_pb2 import ExceptionEvent, ExceptionLevel
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.themes import PADX, PADY
|
||||
from core.gui.widgets import CodeText
|
||||
|
@ -15,14 +15,14 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class AlertsDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Alerts")
|
||||
self.tree = None
|
||||
self.codetext = None
|
||||
self.alarm_map = {}
|
||||
self.tree: Optional[ttk.Treeview] = None
|
||||
self.codetext: Optional[CodeText] = None
|
||||
self.alarm_map: Dict[int, ExceptionEvent] = {}
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.top.rowconfigure(1, weight=1)
|
||||
|
@ -97,13 +97,13 @@ class AlertsDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Close", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def reset_alerts(self):
|
||||
def reset_alerts(self) -> None:
|
||||
self.codetext.text.delete("1.0", tk.END)
|
||||
for item in self.tree.get_children():
|
||||
self.tree.delete(item)
|
||||
self.app.statusbar.core_alarms.clear()
|
||||
|
||||
def click_select(self, event: tk.Event):
|
||||
def click_select(self, event: tk.Event) -> None:
|
||||
current = self.tree.selection()[0]
|
||||
alarm = self.alarm_map[current]
|
||||
self.codetext.text.config(state=tk.NORMAL)
|
||||
|
|
|
@ -7,38 +7,43 @@ from typing import TYPE_CHECKING
|
|||
|
||||
from core.gui import validation
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.themes import FRAME_PAD, PADX, PADY
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
|
||||
PIXEL_SCALE = 100
|
||||
PIXEL_SCALE: int = 100
|
||||
|
||||
|
||||
class SizeAndScaleDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
"""
|
||||
create an instance for size and scale object
|
||||
"""
|
||||
super().__init__(app, "Canvas Size and Scale")
|
||||
self.canvas = self.app.canvas
|
||||
self.section_font = font.Font(weight="bold")
|
||||
self.canvas: CanvasGraph = self.app.canvas
|
||||
self.section_font: font.Font = font.Font(weight="bold")
|
||||
width, height = self.canvas.current_dimensions
|
||||
self.pixel_width = tk.IntVar(value=width)
|
||||
self.pixel_height = tk.IntVar(value=height)
|
||||
self.pixel_width: tk.IntVar = tk.IntVar(value=width)
|
||||
self.pixel_height: tk.IntVar = tk.IntVar(value=height)
|
||||
location = self.app.core.location
|
||||
self.x = tk.DoubleVar(value=location.x)
|
||||
self.y = tk.DoubleVar(value=location.y)
|
||||
self.lat = tk.DoubleVar(value=location.lat)
|
||||
self.lon = tk.DoubleVar(value=location.lon)
|
||||
self.alt = tk.DoubleVar(value=location.alt)
|
||||
self.scale = tk.DoubleVar(value=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.save_default = tk.BooleanVar(value=False)
|
||||
self.x: tk.DoubleVar = tk.DoubleVar(value=location.x)
|
||||
self.y: tk.DoubleVar = tk.DoubleVar(value=location.y)
|
||||
self.lat: tk.DoubleVar = tk.DoubleVar(value=location.lat)
|
||||
self.lon: tk.DoubleVar = tk.DoubleVar(value=location.lon)
|
||||
self.alt: tk.DoubleVar = tk.DoubleVar(value=location.alt)
|
||||
self.scale: tk.DoubleVar = tk.DoubleVar(value=location.scale)
|
||||
self.meters_width: tk.IntVar = tk.IntVar(
|
||||
value=width / PIXEL_SCALE * location.scale
|
||||
)
|
||||
self.meters_height: tk.IntVar = tk.IntVar(
|
||||
value=height / PIXEL_SCALE * location.scale
|
||||
)
|
||||
self.save_default: tk.BooleanVar = tk.BooleanVar(value=False)
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.draw_size()
|
||||
self.draw_scale()
|
||||
|
@ -47,7 +52,7 @@ class SizeAndScaleDialog(Dialog):
|
|||
self.draw_spacer()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_size(self):
|
||||
def draw_size(self) -> None:
|
||||
label_frame = ttk.Labelframe(self.top, text="Size", padding=FRAME_PAD)
|
||||
label_frame.grid(sticky="ew")
|
||||
label_frame.columnconfigure(0, weight=1)
|
||||
|
@ -84,7 +89,7 @@ class SizeAndScaleDialog(Dialog):
|
|||
label = ttk.Label(frame, text="Meters")
|
||||
label.grid(row=0, column=4, sticky="w")
|
||||
|
||||
def draw_scale(self):
|
||||
def draw_scale(self) -> None:
|
||||
label_frame = ttk.Labelframe(self.top, text="Scale", padding=FRAME_PAD)
|
||||
label_frame.grid(sticky="ew")
|
||||
label_frame.columnconfigure(0, weight=1)
|
||||
|
@ -99,7 +104,7 @@ class SizeAndScaleDialog(Dialog):
|
|||
label = ttk.Label(frame, text="Meters")
|
||||
label.grid(row=0, column=2, sticky="w")
|
||||
|
||||
def draw_reference_point(self):
|
||||
def draw_reference_point(self) -> None:
|
||||
label_frame = ttk.Labelframe(
|
||||
self.top, text="Reference Point", padding=FRAME_PAD
|
||||
)
|
||||
|
@ -150,13 +155,13 @@ class SizeAndScaleDialog(Dialog):
|
|||
entry = validation.FloatEntry(frame, textvariable=self.alt)
|
||||
entry.grid(row=0, column=5, sticky="ew")
|
||||
|
||||
def draw_save_as_default(self):
|
||||
def draw_save_as_default(self) -> None:
|
||||
button = ttk.Checkbutton(
|
||||
self.top, text="Save as default?", variable=self.save_default
|
||||
)
|
||||
button.grid(sticky="w", pady=PADY)
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.columnconfigure(0, weight=1)
|
||||
frame.columnconfigure(1, weight=1)
|
||||
|
@ -168,7 +173,7 @@ class SizeAndScaleDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
width, height = self.pixel_width.get(), self.pixel_height.get()
|
||||
self.canvas.redraw_canvas((width, height))
|
||||
if self.canvas.wallpaper:
|
||||
|
|
|
@ -4,10 +4,11 @@ set wallpaper
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
|
||||
from core.gui.appconfig import BACKGROUNDS_PATH
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.images import Images
|
||||
from core.gui.themes import PADX, PADY
|
||||
from core.gui.widgets import image_chooser
|
||||
|
@ -17,20 +18,22 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class CanvasWallpaperDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
"""
|
||||
create an instance of CanvasWallpaper object
|
||||
"""
|
||||
super().__init__(app, "Canvas Background")
|
||||
self.canvas = self.app.canvas
|
||||
self.scale_option = tk.IntVar(value=self.canvas.scale_option.get())
|
||||
self.adjust_to_dim = tk.BooleanVar(value=self.canvas.adjust_to_dim.get())
|
||||
self.filename = tk.StringVar(value=self.canvas.wallpaper_file)
|
||||
self.image_label = None
|
||||
self.options = []
|
||||
self.canvas: CanvasGraph = self.app.canvas
|
||||
self.scale_option: tk.IntVar = tk.IntVar(value=self.canvas.scale_option.get())
|
||||
self.adjust_to_dim: tk.BooleanVar = tk.BooleanVar(
|
||||
value=self.canvas.adjust_to_dim.get()
|
||||
)
|
||||
self.filename: tk.StringVar = tk.StringVar(value=self.canvas.wallpaper_file)
|
||||
self.image_label: Optional[ttk.Label] = None
|
||||
self.options: List[ttk.Radiobutton] = []
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.draw_image()
|
||||
self.draw_image_label()
|
||||
|
@ -40,19 +43,19 @@ class CanvasWallpaperDialog(Dialog):
|
|||
self.draw_spacer()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_image(self):
|
||||
def draw_image(self) -> None:
|
||||
self.image_label = ttk.Label(
|
||||
self.top, text="(image preview)", width=32, anchor=tk.CENTER
|
||||
)
|
||||
self.image_label.grid(pady=PADY)
|
||||
|
||||
def draw_image_label(self):
|
||||
def draw_image_label(self) -> None:
|
||||
label = ttk.Label(self.top, text="Image filename: ")
|
||||
label.grid(sticky="ew")
|
||||
if self.filename.get():
|
||||
self.draw_preview()
|
||||
|
||||
def draw_image_selection(self):
|
||||
def draw_image_selection(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.columnconfigure(0, weight=2)
|
||||
frame.columnconfigure(1, weight=1)
|
||||
|
@ -69,7 +72,7 @@ class CanvasWallpaperDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Clear", command=self.click_clear)
|
||||
button.grid(row=0, column=2, sticky="ew")
|
||||
|
||||
def draw_options(self):
|
||||
def draw_options(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.columnconfigure(0, weight=1)
|
||||
frame.columnconfigure(1, weight=1)
|
||||
|
@ -101,7 +104,7 @@ class CanvasWallpaperDialog(Dialog):
|
|||
button.grid(row=0, column=3, sticky="ew")
|
||||
self.options.append(button)
|
||||
|
||||
def draw_additional_options(self):
|
||||
def draw_additional_options(self) -> None:
|
||||
checkbutton = ttk.Checkbutton(
|
||||
self.top,
|
||||
text="Adjust canvas size to image dimensions",
|
||||
|
@ -110,7 +113,7 @@ class CanvasWallpaperDialog(Dialog):
|
|||
)
|
||||
checkbutton.grid(sticky="ew", padx=PADX)
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(pady=PADY, sticky="ew")
|
||||
frame.columnconfigure(0, weight=1)
|
||||
|
@ -122,18 +125,18 @@ class CanvasWallpaperDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_open_image(self):
|
||||
def click_open_image(self) -> None:
|
||||
filename = image_chooser(self, BACKGROUNDS_PATH)
|
||||
if filename:
|
||||
self.filename.set(filename)
|
||||
self.draw_preview()
|
||||
|
||||
def draw_preview(self):
|
||||
def draw_preview(self) -> None:
|
||||
image = Images.create(self.filename.get(), 250, 135)
|
||||
self.image_label.config(image=image)
|
||||
self.image_label.image = image
|
||||
|
||||
def click_clear(self):
|
||||
def click_clear(self) -> None:
|
||||
"""
|
||||
delete like shown in image link entry if there is any
|
||||
"""
|
||||
|
@ -143,7 +146,7 @@ class CanvasWallpaperDialog(Dialog):
|
|||
self.image_label.config(image="", width=32)
|
||||
self.image_label.image = None
|
||||
|
||||
def click_adjust_canvas(self):
|
||||
def click_adjust_canvas(self) -> None:
|
||||
# deselect all radio buttons and grey them out
|
||||
if self.adjust_to_dim.get():
|
||||
self.scale_option.set(0)
|
||||
|
@ -155,7 +158,7 @@ class CanvasWallpaperDialog(Dialog):
|
|||
for option in self.options:
|
||||
option.config(state=tk.NORMAL)
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
self.canvas.scale_option.set(self.scale_option.get())
|
||||
self.canvas.adjust_to_dim.set(self.adjust_to_dim.get())
|
||||
self.canvas.show_grid.click_handler()
|
||||
|
|
|
@ -3,7 +3,7 @@ custom color picker
|
|||
"""
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional, Tuple
|
||||
|
||||
from core.gui import validation
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -18,23 +18,23 @@ class ColorPickerDialog(Dialog):
|
|||
self, master: tk.BaseWidget, app: "Application", initcolor: str = "#000000"
|
||||
):
|
||||
super().__init__(app, "Color Picker", master=master)
|
||||
self.red_entry = None
|
||||
self.blue_entry = None
|
||||
self.green_entry = None
|
||||
self.hex_entry = None
|
||||
self.red_label = None
|
||||
self.green_label = None
|
||||
self.blue_label = None
|
||||
self.display = None
|
||||
self.color = initcolor
|
||||
self.red_entry: Optional[validation.RgbEntry] = None
|
||||
self.blue_entry: Optional[validation.RgbEntry] = None
|
||||
self.green_entry: Optional[validation.RgbEntry] = None
|
||||
self.hex_entry: Optional[validation.HexEntry] = None
|
||||
self.red_label: Optional[ttk.Label] = None
|
||||
self.green_label: Optional[ttk.Label] = None
|
||||
self.blue_label: Optional[ttk.Label] = None
|
||||
self.display: Optional[tk.Frame] = None
|
||||
self.color: str = initcolor
|
||||
red, green, blue = self.get_rgb(initcolor)
|
||||
self.red = tk.IntVar(value=red)
|
||||
self.blue = tk.IntVar(value=blue)
|
||||
self.green = tk.IntVar(value=green)
|
||||
self.hex = tk.StringVar(value=initcolor)
|
||||
self.red_scale = tk.IntVar(value=red)
|
||||
self.green_scale = tk.IntVar(value=green)
|
||||
self.blue_scale = tk.IntVar(value=blue)
|
||||
self.red: tk.IntVar = tk.IntVar(value=red)
|
||||
self.blue: tk.IntVar = tk.IntVar(value=blue)
|
||||
self.green: tk.IntVar = tk.IntVar(value=green)
|
||||
self.hex: tk.StringVar = tk.StringVar(value=initcolor)
|
||||
self.red_scale: tk.IntVar = tk.IntVar(value=red)
|
||||
self.green_scale: tk.IntVar = tk.IntVar(value=green)
|
||||
self.blue_scale: tk.IntVar = tk.IntVar(value=blue)
|
||||
self.draw()
|
||||
self.set_bindings()
|
||||
|
||||
|
@ -42,7 +42,7 @@ class ColorPickerDialog(Dialog):
|
|||
self.show()
|
||||
return self.color
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(3, weight=1)
|
||||
|
||||
|
@ -136,7 +136,7 @@ class ColorPickerDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def set_bindings(self):
|
||||
def set_bindings(self) -> None:
|
||||
self.red_entry.bind("<FocusIn>", lambda x: self.current_focus("rgb"))
|
||||
self.green_entry.bind("<FocusIn>", lambda x: self.current_focus("rgb"))
|
||||
self.blue_entry.bind("<FocusIn>", lambda x: self.current_focus("rgb"))
|
||||
|
@ -146,7 +146,7 @@ class ColorPickerDialog(Dialog):
|
|||
self.blue.trace_add("write", self.update_color)
|
||||
self.hex.trace_add("write", self.update_color)
|
||||
|
||||
def button_ok(self):
|
||||
def button_ok(self) -> None:
|
||||
self.color = self.hex.get()
|
||||
self.destroy()
|
||||
|
||||
|
@ -159,10 +159,10 @@ class ColorPickerDialog(Dialog):
|
|||
green = self.green_entry.get()
|
||||
return "#%02x%02x%02x" % (int(red), int(green), int(blue))
|
||||
|
||||
def current_focus(self, focus: str):
|
||||
def current_focus(self, focus: str) -> None:
|
||||
self.focus = focus
|
||||
|
||||
def update_color(self, arg1=None, arg2=None, arg3=None):
|
||||
def update_color(self, arg1=None, arg2=None, arg3=None) -> None:
|
||||
if self.focus == "rgb":
|
||||
red = self.red_entry.get()
|
||||
blue = self.blue_entry.get()
|
||||
|
@ -184,7 +184,7 @@ class ColorPickerDialog(Dialog):
|
|||
self.display.config(background=hex_code)
|
||||
self.set_label(str(red), str(green), str(blue))
|
||||
|
||||
def scale_callback(self, var: tk.IntVar, color_var: tk.IntVar):
|
||||
def scale_callback(self, var: tk.IntVar, color_var: tk.IntVar) -> None:
|
||||
color_var.set(var.get())
|
||||
self.focus = "rgb"
|
||||
self.update_color()
|
||||
|
@ -194,17 +194,17 @@ class ColorPickerDialog(Dialog):
|
|||
self.green_scale.set(green)
|
||||
self.blue_scale.set(blue)
|
||||
|
||||
def set_entry(self, red: int, green: int, blue: int):
|
||||
def set_entry(self, red: int, green: int, blue: int) -> None:
|
||||
self.red.set(red)
|
||||
self.green.set(green)
|
||||
self.blue.set(blue)
|
||||
|
||||
def set_label(self, red: str, green: str, blue: str):
|
||||
def set_label(self, red: str, green: str, blue: str) -> None:
|
||||
self.red_label.configure(background="#%02x%02x%02x" % (int(red), 0, 0))
|
||||
self.green_label.configure(background="#%02x%02x%02x" % (0, int(green), 0))
|
||||
self.blue_label.configure(background="#%02x%02x%02x" % (0, 0, int(blue)))
|
||||
|
||||
def get_rgb(self, hex_code: str) -> [int, int, int]:
|
||||
def get_rgb(self, hex_code: str) -> Tuple[int, int, int]:
|
||||
"""
|
||||
convert a valid hex code to RGB values
|
||||
"""
|
||||
|
|
|
@ -4,10 +4,11 @@ Service configuration dialog
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, List
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set
|
||||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc.common_pb2 import ConfigOption
|
||||
from core.api.grpc.services_pb2 import ServiceValidationMode
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.themes import FRAME_PAD, PADX, PADY
|
||||
|
@ -16,6 +17,7 @@ from core.gui.widgets import CodeText, ConfigFrame, ListboxScroll
|
|||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
from core.gui.graph.node import CanvasNode
|
||||
from core.gui.coreclient import CoreClient
|
||||
|
||||
|
||||
class ConfigServiceConfigDialog(Dialog):
|
||||
|
@ -26,56 +28,53 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
service_name: str,
|
||||
canvas_node: "CanvasNode",
|
||||
node_id: int,
|
||||
):
|
||||
) -> None:
|
||||
title = f"{service_name} Config Service"
|
||||
super().__init__(app, title, master=master)
|
||||
self.core = app.core
|
||||
self.canvas_node = canvas_node
|
||||
self.node_id = node_id
|
||||
self.service_name = service_name
|
||||
self.radiovar = tk.IntVar()
|
||||
self.core: "CoreClient" = app.core
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node_id: int = node_id
|
||||
self.service_name: str = service_name
|
||||
self.radiovar: tk.IntVar = tk.IntVar()
|
||||
self.radiovar.set(2)
|
||||
self.directories = []
|
||||
self.templates = []
|
||||
self.dependencies = []
|
||||
self.executables = []
|
||||
self.startup_commands = []
|
||||
self.validation_commands = []
|
||||
self.shutdown_commands = []
|
||||
self.default_startup = []
|
||||
self.default_validate = []
|
||||
self.default_shutdown = []
|
||||
self.validation_mode = None
|
||||
self.validation_time = None
|
||||
self.validation_period = tk.StringVar()
|
||||
self.modes = []
|
||||
self.mode_configs = {}
|
||||
|
||||
self.notebook = None
|
||||
self.templates_combobox = None
|
||||
self.modes_combobox = None
|
||||
self.startup_commands_listbox = None
|
||||
self.shutdown_commands_listbox = None
|
||||
self.validate_commands_listbox = None
|
||||
self.validation_time_entry = None
|
||||
self.validation_mode_entry = None
|
||||
self.template_text = None
|
||||
self.validation_period_entry = None
|
||||
self.original_service_files = {}
|
||||
self.temp_service_files = {}
|
||||
self.modified_files = set()
|
||||
self.config_frame = None
|
||||
self.default_config = None
|
||||
self.config = None
|
||||
|
||||
self.has_error = False
|
||||
self.directories: List[str] = []
|
||||
self.templates: List[str] = []
|
||||
self.dependencies: List[str] = []
|
||||
self.executables: List[str] = []
|
||||
self.startup_commands: List[str] = []
|
||||
self.validation_commands: List[str] = []
|
||||
self.shutdown_commands: List[str] = []
|
||||
self.default_startup: List[str] = []
|
||||
self.default_validate: List[str] = []
|
||||
self.default_shutdown: List[str] = []
|
||||
self.validation_mode: Optional[ServiceValidationMode] = None
|
||||
self.validation_time: Optional[int] = None
|
||||
self.validation_period: tk.StringVar = tk.StringVar()
|
||||
self.modes: List[str] = []
|
||||
self.mode_configs: Dict[str, str] = {}
|
||||
|
||||
self.notebook: Optional[ttk.Notebook] = None
|
||||
self.templates_combobox: Optional[ttk.Combobox] = None
|
||||
self.modes_combobox: Optional[ttk.Combobox] = None
|
||||
self.startup_commands_listbox: Optional[tk.Listbox] = None
|
||||
self.shutdown_commands_listbox: Optional[tk.Listbox] = None
|
||||
self.validate_commands_listbox: Optional[tk.Listbox] = None
|
||||
self.validation_time_entry: Optional[ttk.Entry] = None
|
||||
self.validation_mode_entry: Optional[ttk.Entry] = None
|
||||
self.template_text: Optional[CodeText] = None
|
||||
self.validation_period_entry: Optional[ttk.Entry] = None
|
||||
self.original_service_files: Dict[str, str] = {}
|
||||
self.temp_service_files: Dict[str, str] = {}
|
||||
self.modified_files: Set[str] = set()
|
||||
self.config_frame: Optional[ConfigFrame] = None
|
||||
self.default_config: Dict[str, str] = {}
|
||||
self.config: Dict[str, ConfigOption] = {}
|
||||
self.has_error: bool = False
|
||||
self.load()
|
||||
|
||||
if not self.has_error:
|
||||
self.draw()
|
||||
|
||||
def load(self):
|
||||
def load(self) -> None:
|
||||
try:
|
||||
self.core.create_nodes_and_links()
|
||||
service = self.core.config_services[self.service_name]
|
||||
|
@ -116,7 +115,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
self.app.show_grpc_exception("Get Config Service Error", e)
|
||||
self.has_error = True
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
|
||||
|
@ -130,7 +129,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
self.draw_tab_validation()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_tab_files(self):
|
||||
def draw_tab_files(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="nsew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -174,7 +173,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
)
|
||||
self.template_text.text.bind("<FocusOut>", self.update_template_file_data)
|
||||
|
||||
def draw_tab_config(self):
|
||||
def draw_tab_config(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="nsew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -198,7 +197,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
self.config_frame.grid(sticky="nsew", pady=PADY)
|
||||
tab.rowconfigure(self.config_frame.grid_info()["row"], weight=1)
|
||||
|
||||
def draw_tab_startstop(self):
|
||||
def draw_tab_startstop(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="nsew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -239,7 +238,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
elif i == 2:
|
||||
self.validate_commands_listbox = listbox_scroll.listbox
|
||||
|
||||
def draw_tab_validation(self):
|
||||
def draw_tab_validation(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="ew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -298,7 +297,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
for dependency in self.dependencies:
|
||||
listbox_scroll.listbox.insert("end", dependency)
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(4):
|
||||
|
@ -312,7 +311,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=3, sticky="ew")
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
current_listbox = self.master.current.listbox
|
||||
if not self.is_custom():
|
||||
self.canvas_node.config_service_configs.pop(self.service_name, None)
|
||||
|
@ -333,18 +332,18 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
current_listbox.itemconfig(all_current.index(self.service_name), bg="green")
|
||||
self.destroy()
|
||||
|
||||
def handle_template_changed(self, event: tk.Event):
|
||||
def handle_template_changed(self, event: tk.Event) -> None:
|
||||
template = self.templates_combobox.get()
|
||||
self.template_text.text.delete(1.0, "end")
|
||||
self.template_text.text.insert("end", self.temp_service_files[template])
|
||||
|
||||
def handle_mode_changed(self, event: tk.Event):
|
||||
def handle_mode_changed(self, event: tk.Event) -> None:
|
||||
mode = self.modes_combobox.get()
|
||||
config = self.mode_configs[mode]
|
||||
logging.info("mode config: %s", config)
|
||||
self.config_frame.set_values(config)
|
||||
|
||||
def update_template_file_data(self, event: tk.Event):
|
||||
def update_template_file_data(self, event: tk.Event) -> None:
|
||||
scrolledtext = event.widget
|
||||
template = self.templates_combobox.get()
|
||||
self.temp_service_files[template] = scrolledtext.get(1.0, "end")
|
||||
|
@ -353,7 +352,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
else:
|
||||
self.modified_files.discard(template)
|
||||
|
||||
def is_custom(self):
|
||||
def is_custom(self) -> bool:
|
||||
has_custom_templates = len(self.modified_files) > 0
|
||||
has_custom_config = False
|
||||
if self.config_frame:
|
||||
|
@ -361,7 +360,7 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
has_custom_config = self.default_config != current
|
||||
return has_custom_templates or has_custom_config
|
||||
|
||||
def click_defaults(self):
|
||||
def click_defaults(self) -> None:
|
||||
self.canvas_node.config_service_configs.pop(self.service_name, None)
|
||||
logging.info(
|
||||
"cleared config service config: %s", self.canvas_node.config_service_configs
|
||||
|
@ -374,12 +373,12 @@ class ConfigServiceConfigDialog(Dialog):
|
|||
logging.info("resetting defaults: %s", self.default_config)
|
||||
self.config_frame.set_values(self.default_config)
|
||||
|
||||
def click_copy(self):
|
||||
def click_copy(self) -> None:
|
||||
pass
|
||||
|
||||
def append_commands(
|
||||
self, commands: List[str], listbox: tk.Listbox, to_add: List[str]
|
||||
):
|
||||
) -> None:
|
||||
for cmd in to_add:
|
||||
commands.append(cmd)
|
||||
listbox.insert(tk.END, cmd)
|
||||
|
|
|
@ -15,17 +15,16 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class CopyServiceConfigDialog(Dialog):
|
||||
def __init__(self, master: tk.BaseWidget, app: "Application", node_id: int):
|
||||
def __init__(self, master: tk.BaseWidget, app: "Application", node_id: int) -> None:
|
||||
super().__init__(app, f"Copy services to node {node_id}", master=master)
|
||||
self.parent = master
|
||||
self.node_id = node_id
|
||||
self.service_configs = app.core.service_configs
|
||||
self.file_configs = app.core.file_configs
|
||||
|
||||
self.tree = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.tree = ttk.Treeview(self.top)
|
||||
self.tree.grid(row=0, column=0, sticky="ew", padx=PADX)
|
||||
|
@ -88,7 +87,7 @@ class CopyServiceConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=2, sticky="ew", padx=PADX)
|
||||
|
||||
def click_copy(self):
|
||||
def click_copy(self) -> None:
|
||||
selected = self.tree.selection()
|
||||
if selected:
|
||||
item = self.tree.item(selected[0])
|
||||
|
@ -127,7 +126,7 @@ class CopyServiceConfigDialog(Dialog):
|
|||
)
|
||||
self.destroy()
|
||||
|
||||
def click_view(self):
|
||||
def click_view(self) -> None:
|
||||
selected = self.tree.selection()
|
||||
data = ""
|
||||
if selected:
|
||||
|
@ -159,7 +158,7 @@ class CopyServiceConfigDialog(Dialog):
|
|||
)
|
||||
dialog.show()
|
||||
|
||||
def get_node_service(self, selected: Tuple[str]) -> [int, str]:
|
||||
def get_node_service(self, selected: Tuple[str]) -> Tuple[int, str]:
|
||||
service_tree_id = self.tree.parent(selected[0])
|
||||
service_name = self.tree.item(service_tree_id)["text"]
|
||||
node_tree_id = self.tree.parent(service_tree_id)
|
||||
|
@ -175,14 +174,14 @@ class ViewConfigDialog(Dialog):
|
|||
node_id: int,
|
||||
data: str,
|
||||
filename: str = None,
|
||||
):
|
||||
) -> None:
|
||||
super().__init__(app, f"n{node_id} config data", master=master)
|
||||
self.data = data
|
||||
self.service_data = None
|
||||
self.filepath = tk.StringVar(value=f"/tmp/services.tmp-n{node_id}-{filename}")
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
frame = ttk.Frame(self.top, padding=FRAME_PAD)
|
||||
frame.columnconfigure(0, weight=1)
|
||||
|
|
|
@ -2,7 +2,9 @@ import logging
|
|||
import tkinter as tk
|
||||
from pathlib import Path
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Set
|
||||
from typing import TYPE_CHECKING, Optional, Set
|
||||
|
||||
from PIL.ImageTk import PhotoImage
|
||||
|
||||
from core.gui import nodeutils
|
||||
from core.gui.appconfig import ICONS_PATH, CustomNode
|
||||
|
@ -19,15 +21,15 @@ if TYPE_CHECKING:
|
|||
class ServicesSelectDialog(Dialog):
|
||||
def __init__(
|
||||
self, master: tk.BaseWidget, app: "Application", current_services: Set[str]
|
||||
):
|
||||
) -> None:
|
||||
super().__init__(app, "Node Services", master=master)
|
||||
self.groups = None
|
||||
self.services = None
|
||||
self.current = None
|
||||
self.current_services = set(current_services)
|
||||
self.groups: Optional[ListboxScroll] = None
|
||||
self.services: Optional[CheckboxList] = None
|
||||
self.current: Optional[ListboxScroll] = None
|
||||
self.current_services: Set[str] = current_services
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
|
||||
|
@ -77,7 +79,7 @@ class ServicesSelectDialog(Dialog):
|
|||
# trigger group change
|
||||
self.groups.listbox.event_generate("<<ListboxSelect>>")
|
||||
|
||||
def handle_group_change(self, event: tk.Event):
|
||||
def handle_group_change(self, event: tk.Event) -> None:
|
||||
selection = self.groups.listbox.curselection()
|
||||
if selection:
|
||||
index = selection[0]
|
||||
|
@ -87,7 +89,7 @@ class ServicesSelectDialog(Dialog):
|
|||
checked = name in self.current_services
|
||||
self.services.add(name, checked)
|
||||
|
||||
def service_clicked(self, name: str, var: tk.BooleanVar):
|
||||
def service_clicked(self, name: str, var: tk.BooleanVar) -> None:
|
||||
if var.get() and name not in self.current_services:
|
||||
self.current_services.add(name)
|
||||
elif not var.get() and name in self.current_services:
|
||||
|
@ -96,34 +98,34 @@ class ServicesSelectDialog(Dialog):
|
|||
for name in sorted(self.current_services):
|
||||
self.current.listbox.insert(tk.END, name)
|
||||
|
||||
def click_cancel(self):
|
||||
def click_cancel(self) -> None:
|
||||
self.current_services = None
|
||||
self.destroy()
|
||||
|
||||
|
||||
class CustomNodesDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Custom Nodes")
|
||||
self.edit_button = None
|
||||
self.delete_button = None
|
||||
self.nodes_list = None
|
||||
self.name = tk.StringVar()
|
||||
self.image_button = None
|
||||
self.image = None
|
||||
self.image_file = None
|
||||
self.services = set()
|
||||
self.selected = None
|
||||
self.selected_index = None
|
||||
self.edit_button: Optional[ttk.Button] = None
|
||||
self.delete_button: Optional[ttk.Button] = None
|
||||
self.nodes_list: Optional[ListboxScroll] = None
|
||||
self.name: tk.StringVar = tk.StringVar()
|
||||
self.image_button: Optional[ttk.Button] = None
|
||||
self.image: Optional[PhotoImage] = None
|
||||
self.image_file: Optional[str] = None
|
||||
self.services: Set[str] = set()
|
||||
self.selected: Optional[str] = None
|
||||
self.selected_index: Optional[int] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.draw_node_config()
|
||||
self.draw_node_buttons()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_node_config(self):
|
||||
def draw_node_config(self) -> None:
|
||||
frame = ttk.LabelFrame(self.top, text="Nodes", padding=FRAME_PAD)
|
||||
frame.grid(sticky="nsew", pady=PADY)
|
||||
frame.columnconfigure(0, weight=1)
|
||||
|
@ -147,7 +149,7 @@ class CustomNodesDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Services", command=self.click_services)
|
||||
button.grid(sticky="ew")
|
||||
|
||||
def draw_node_buttons(self):
|
||||
def draw_node_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew", pady=PADY)
|
||||
for i in range(3):
|
||||
|
@ -166,7 +168,7 @@ class CustomNodesDialog(Dialog):
|
|||
)
|
||||
self.delete_button.grid(row=0, column=2, sticky="ew")
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -178,14 +180,14 @@ class CustomNodesDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def reset_values(self):
|
||||
def reset_values(self) -> None:
|
||||
self.name.set("")
|
||||
self.image = None
|
||||
self.image_file = None
|
||||
self.services = set()
|
||||
self.image_button.config(image="")
|
||||
|
||||
def click_icon(self):
|
||||
def click_icon(self) -> None:
|
||||
file_path = image_chooser(self, ICONS_PATH)
|
||||
if file_path:
|
||||
image = Images.create(file_path, nodeutils.ICON_SIZE)
|
||||
|
@ -193,24 +195,26 @@ class CustomNodesDialog(Dialog):
|
|||
self.image_file = file_path
|
||||
self.image_button.config(image=self.image)
|
||||
|
||||
def click_services(self):
|
||||
def click_services(self) -> None:
|
||||
dialog = ServicesSelectDialog(self, self.app, self.services)
|
||||
dialog.show()
|
||||
if dialog.current_services is not None:
|
||||
self.services.clear()
|
||||
self.services.update(dialog.current_services)
|
||||
|
||||
def click_save(self):
|
||||
def click_save(self) -> None:
|
||||
self.app.guiconfig.nodes.clear()
|
||||
for name in self.app.core.custom_nodes:
|
||||
node_draw = self.app.core.custom_nodes[name]
|
||||
custom_node = CustomNode(name, node_draw.image_file, node_draw.services)
|
||||
custom_node = CustomNode(
|
||||
name, node_draw.image_file, list(node_draw.services)
|
||||
)
|
||||
self.app.guiconfig.nodes.append(custom_node)
|
||||
logging.info("saving custom nodes: %s", self.app.guiconfig.nodes)
|
||||
self.app.save_config()
|
||||
self.destroy()
|
||||
|
||||
def click_create(self):
|
||||
def click_create(self) -> None:
|
||||
name = self.name.get()
|
||||
if name not in self.app.core.custom_nodes:
|
||||
image_file = Path(self.image_file).stem
|
||||
|
@ -226,7 +230,7 @@ class CustomNodesDialog(Dialog):
|
|||
self.nodes_list.listbox.insert(tk.END, name)
|
||||
self.reset_values()
|
||||
|
||||
def click_edit(self):
|
||||
def click_edit(self) -> None:
|
||||
name = self.name.get()
|
||||
if self.selected:
|
||||
previous_name = self.selected
|
||||
|
@ -247,7 +251,7 @@ class CustomNodesDialog(Dialog):
|
|||
self.nodes_list.listbox.insert(self.selected_index, name)
|
||||
self.nodes_list.listbox.selection_set(self.selected_index)
|
||||
|
||||
def click_delete(self):
|
||||
def click_delete(self) -> None:
|
||||
if self.selected and self.selected in self.app.core.custom_nodes:
|
||||
self.nodes_list.listbox.delete(self.selected_index)
|
||||
del self.app.core.custom_nodes[self.selected]
|
||||
|
@ -255,7 +259,7 @@ class CustomNodesDialog(Dialog):
|
|||
self.nodes_list.listbox.selection_clear(0, tk.END)
|
||||
self.nodes_list.listbox.event_generate("<<ListboxSelect>>")
|
||||
|
||||
def handle_node_select(self, event: tk.Event):
|
||||
def handle_node_select(self, event: tk.Event) -> None:
|
||||
selection = self.nodes_list.listbox.curselection()
|
||||
if selection:
|
||||
self.selected_index = selection[0]
|
||||
|
|
|
@ -16,23 +16,23 @@ class Dialog(tk.Toplevel):
|
|||
title: str,
|
||||
modal: bool = True,
|
||||
master: tk.BaseWidget = None,
|
||||
):
|
||||
) -> None:
|
||||
if master is None:
|
||||
master = app
|
||||
super().__init__(master)
|
||||
self.withdraw()
|
||||
self.app = app
|
||||
self.modal = modal
|
||||
self.app: "Application" = app
|
||||
self.modal: bool = modal
|
||||
self.title(title)
|
||||
self.protocol("WM_DELETE_WINDOW", self.destroy)
|
||||
image = Images.get(ImageEnum.CORE, 16)
|
||||
self.tk.call("wm", "iconphoto", self._w, image)
|
||||
self.columnconfigure(0, weight=1)
|
||||
self.rowconfigure(0, weight=1)
|
||||
self.top = ttk.Frame(self, padding=DIALOG_PAD)
|
||||
self.top: ttk.Frame = ttk.Frame(self, padding=DIALOG_PAD)
|
||||
self.top.grid(sticky="nsew")
|
||||
|
||||
def show(self):
|
||||
def show(self) -> None:
|
||||
self.transient(self.master)
|
||||
self.focus_force()
|
||||
self.update()
|
||||
|
@ -42,7 +42,7 @@ class Dialog(tk.Toplevel):
|
|||
self.grab_set()
|
||||
self.wait_window()
|
||||
|
||||
def draw_spacer(self, row: int = None):
|
||||
def draw_spacer(self, row: int = None) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(row=row, sticky="nsew")
|
||||
frame.rowconfigure(0, weight=1)
|
||||
|
|
|
@ -4,10 +4,12 @@ emane configuration
|
|||
import tkinter as tk
|
||||
import webbrowser
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional
|
||||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc.common_pb2 import ConfigOption
|
||||
from core.api.grpc.core_pb2 import Node
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.images import ImageEnum, Images
|
||||
from core.gui.themes import PADX, PADY
|
||||
|
@ -19,12 +21,12 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class GlobalEmaneDialog(Dialog):
|
||||
def __init__(self, master: tk.BaseWidget, app: "Application"):
|
||||
def __init__(self, master: tk.BaseWidget, app: "Application") -> None:
|
||||
super().__init__(app, "EMANE Configuration", master=master)
|
||||
self.config_frame = None
|
||||
self.config_frame: Optional[ConfigFrame] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.config_frame = ConfigFrame(self.top, self.app, self.app.core.emane_config)
|
||||
|
@ -33,7 +35,7 @@ class GlobalEmaneDialog(Dialog):
|
|||
self.draw_spacer()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -44,7 +46,7 @@ class GlobalEmaneDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
self.config_frame.parse_config()
|
||||
self.destroy()
|
||||
|
||||
|
@ -57,31 +59,32 @@ class EmaneModelDialog(Dialog):
|
|||
canvas_node: "CanvasNode",
|
||||
model: str,
|
||||
iface_id: int = None,
|
||||
):
|
||||
) -> None:
|
||||
super().__init__(
|
||||
app, f"{canvas_node.core_node.name} {model} Configuration", master=master
|
||||
)
|
||||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.model = f"emane_{model}"
|
||||
self.iface_id = iface_id
|
||||
self.config_frame = None
|
||||
self.has_error = False
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node: Node = canvas_node.core_node
|
||||
self.model: str = f"emane_{model}"
|
||||
self.iface_id: int = iface_id
|
||||
self.config_frame: Optional[ConfigFrame] = None
|
||||
self.has_error: bool = False
|
||||
try:
|
||||
self.config = self.canvas_node.emane_model_configs.get(
|
||||
config = self.canvas_node.emane_model_configs.get(
|
||||
(self.model, self.iface_id)
|
||||
)
|
||||
if not self.config:
|
||||
self.config = self.app.core.get_emane_model_config(
|
||||
if not config:
|
||||
config = self.app.core.get_emane_model_config(
|
||||
self.node.id, self.model, self.iface_id
|
||||
)
|
||||
self.config: Dict[str, ConfigOption] = config
|
||||
self.draw()
|
||||
except grpc.RpcError as e:
|
||||
self.app.show_grpc_exception("Get EMANE Config Error", e)
|
||||
self.has_error = True
|
||||
self.has_error: bool = True
|
||||
self.destroy()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.config_frame = ConfigFrame(self.top, self.app, self.config)
|
||||
|
@ -90,7 +93,7 @@ class EmaneModelDialog(Dialog):
|
|||
self.draw_spacer()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -101,7 +104,7 @@ class EmaneModelDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
self.config_frame.parse_config()
|
||||
key = (self.model, self.iface_id)
|
||||
self.canvas_node.emane_model_configs[key] = self.config
|
||||
|
@ -109,18 +112,21 @@ class EmaneModelDialog(Dialog):
|
|||
|
||||
|
||||
class EmaneConfigDialog(Dialog):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode"):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
|
||||
super().__init__(app, f"{canvas_node.core_node.name} EMANE Configuration")
|
||||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.radiovar = tk.IntVar()
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node: Node = canvas_node.core_node
|
||||
self.radiovar: tk.IntVar = tk.IntVar()
|
||||
self.radiovar.set(1)
|
||||
self.emane_models = [x.split("_")[1] for x in self.app.core.emane_models]
|
||||
self.emane_model = tk.StringVar(value=self.node.emane.split("_")[1])
|
||||
self.emane_model_button = None
|
||||
self.emane_models: List[str] = [
|
||||
x.split("_")[1] for x in self.app.core.emane_models
|
||||
]
|
||||
model = self.node.emane.split("_")[1]
|
||||
self.emane_model: tk.StringVar = tk.StringVar(value=model)
|
||||
self.emane_model_button: Optional[ttk.Button] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.draw_emane_configuration()
|
||||
self.draw_emane_models()
|
||||
|
@ -128,7 +134,7 @@ class EmaneConfigDialog(Dialog):
|
|||
self.draw_spacer()
|
||||
self.draw_apply_and_cancel()
|
||||
|
||||
def draw_emane_configuration(self):
|
||||
def draw_emane_configuration(self) -> None:
|
||||
"""
|
||||
draw the main frame for emane configuration
|
||||
"""
|
||||
|
@ -153,7 +159,7 @@ class EmaneConfigDialog(Dialog):
|
|||
button.image = image
|
||||
button.grid(sticky="ew", pady=PADY)
|
||||
|
||||
def draw_emane_models(self):
|
||||
def draw_emane_models(self) -> None:
|
||||
"""
|
||||
create a combobox that has all the known emane models
|
||||
"""
|
||||
|
@ -174,7 +180,7 @@ class EmaneConfigDialog(Dialog):
|
|||
combobox.grid(row=0, column=1, sticky="ew")
|
||||
combobox.bind("<<ComboboxSelected>>", self.emane_model_change)
|
||||
|
||||
def draw_emane_buttons(self):
|
||||
def draw_emane_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew", pady=PADY)
|
||||
for i in range(2):
|
||||
|
@ -202,7 +208,7 @@ class EmaneConfigDialog(Dialog):
|
|||
button.image = image
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def draw_apply_and_cancel(self):
|
||||
def draw_apply_and_cancel(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -214,11 +220,11 @@ class EmaneConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_emane_config(self):
|
||||
def click_emane_config(self) -> None:
|
||||
dialog = GlobalEmaneDialog(self, self.app)
|
||||
dialog.show()
|
||||
|
||||
def click_model_config(self):
|
||||
def click_model_config(self) -> None:
|
||||
"""
|
||||
draw emane model configuration
|
||||
"""
|
||||
|
@ -227,13 +233,13 @@ class EmaneConfigDialog(Dialog):
|
|||
if not dialog.has_error:
|
||||
dialog.show()
|
||||
|
||||
def emane_model_change(self, event: tk.Event):
|
||||
def emane_model_change(self, event: tk.Event) -> None:
|
||||
"""
|
||||
update emane model options button
|
||||
"""
|
||||
model_name = self.emane_model.get()
|
||||
self.emane_model_button.config(text=f"{model_name} options")
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
self.node.emane = f"emane_{self.emane_model.get()}"
|
||||
self.destroy()
|
||||
|
|
|
@ -10,7 +10,7 @@ class EmaneInstallDialog(Dialog):
|
|||
super().__init__(app, "EMANE Error")
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
label = ttk.Label(self.top, text="EMANE needs to be installed!")
|
||||
label.grid(sticky="ew", pady=PADY)
|
||||
|
@ -21,5 +21,5 @@ class EmaneInstallDialog(Dialog):
|
|||
button = ttk.Button(self.top, text="Close", command=self.destroy)
|
||||
button.grid(sticky="ew")
|
||||
|
||||
def click_doc(self):
|
||||
def click_doc(self) -> None:
|
||||
webbrowser.open_new("https://coreemu.github.io/core/emane.html")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.images import ImageEnum, Images
|
||||
|
@ -13,9 +13,9 @@ if TYPE_CHECKING:
|
|||
class ErrorDialog(Dialog):
|
||||
def __init__(self, app: "Application", title: str, details: str) -> None:
|
||||
super().__init__(app, "CORE Exception")
|
||||
self.title = title
|
||||
self.details = details
|
||||
self.error_message = None
|
||||
self.title: str = title
|
||||
self.details: str = details
|
||||
self.error_message: Optional[CodeText] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self) -> None:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog, ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.gui.appconfig import SCRIPT_PATH
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -12,15 +12,15 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class ExecutePythonDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Execute Python Script")
|
||||
self.with_options = tk.IntVar(value=0)
|
||||
self.options = tk.StringVar(value="")
|
||||
self.option_entry = None
|
||||
self.file_entry = None
|
||||
self.with_options: tk.IntVar = tk.IntVar(value=0)
|
||||
self.options: tk.StringVar = tk.StringVar(value="")
|
||||
self.option_entry: Optional[ttk.Entry] = None
|
||||
self.file_entry: Optional[ttk.Entry] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
i = 0
|
||||
frame = ttk.Frame(self.top, padding=FRAME_PAD)
|
||||
frame.columnconfigure(0, weight=1)
|
||||
|
@ -63,13 +63,13 @@ class ExecutePythonDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew", padx=PADX)
|
||||
|
||||
def add_options(self):
|
||||
def add_options(self) -> None:
|
||||
if self.with_options.get():
|
||||
self.option_entry.configure(state="normal")
|
||||
else:
|
||||
self.option_entry.configure(state="disabled")
|
||||
|
||||
def select_file(self):
|
||||
def select_file(self) -> None:
|
||||
file = filedialog.askopenfilename(
|
||||
parent=self.top,
|
||||
initialdir=str(SCRIPT_PATH),
|
||||
|
@ -80,7 +80,7 @@ class ExecutePythonDialog(Dialog):
|
|||
self.file_entry.delete(0, "end")
|
||||
self.file_entry.insert("end", file)
|
||||
|
||||
def script_execute(self):
|
||||
def script_execute(self) -> None:
|
||||
file = self.file_entry.get()
|
||||
options = self.option_entry.get()
|
||||
logging.info("Execute %s with options %s", file, options)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.themes import FRAME_PAD, PADX, PADY
|
||||
|
@ -13,8 +13,8 @@ if TYPE_CHECKING:
|
|||
class FindDialog(Dialog):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Find", modal=False)
|
||||
self.find_text = tk.StringVar(value="")
|
||||
self.tree = None
|
||||
self.find_text: tk.StringVar = tk.StringVar(value="")
|
||||
self.tree: Optional[ttk.Treeview] = None
|
||||
self.draw()
|
||||
self.protocol("WM_DELETE_WINDOW", self.close_dialog)
|
||||
self.bind("<Return>", self.find_node)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -12,15 +12,15 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class HookDialog(Dialog):
|
||||
def __init__(self, master: tk.BaseWidget, app: "Application"):
|
||||
def __init__(self, master: tk.BaseWidget, app: "Application") -> None:
|
||||
super().__init__(app, "Hook", master=master)
|
||||
self.name = tk.StringVar()
|
||||
self.codetext = None
|
||||
self.hook = core_pb2.Hook()
|
||||
self.state = tk.StringVar()
|
||||
self.name: tk.StringVar = tk.StringVar()
|
||||
self.codetext: Optional[CodeText] = None
|
||||
self.hook: core_pb2.Hook = core_pb2.Hook()
|
||||
self.state: tk.StringVar = tk.StringVar()
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(1, weight=1)
|
||||
|
||||
|
@ -66,11 +66,11 @@ class HookDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=lambda: self.destroy())
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def state_change(self, event: tk.Event):
|
||||
def state_change(self, event: tk.Event) -> None:
|
||||
state_name = self.state.get()
|
||||
self.name.set(f"{state_name.lower()}_hook.sh")
|
||||
|
||||
def set(self, hook: core_pb2.Hook):
|
||||
def set(self, hook: core_pb2.Hook) -> None:
|
||||
self.hook = hook
|
||||
self.name.set(hook.file)
|
||||
self.codetext.text.delete(1.0, tk.END)
|
||||
|
@ -78,7 +78,7 @@ class HookDialog(Dialog):
|
|||
state_name = core_pb2.SessionState.Enum.Name(hook.state)
|
||||
self.state.set(state_name)
|
||||
|
||||
def save(self):
|
||||
def save(self) -> None:
|
||||
data = self.codetext.text.get("1.0", tk.END).strip()
|
||||
state_value = core_pb2.SessionState.Enum.Value(self.state.get())
|
||||
self.hook.file = self.name.get()
|
||||
|
@ -88,15 +88,15 @@ class HookDialog(Dialog):
|
|||
|
||||
|
||||
class HooksDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Hooks")
|
||||
self.listbox = None
|
||||
self.edit_button = None
|
||||
self.delete_button = None
|
||||
self.selected = None
|
||||
self.listbox: Optional[tk.Listbox] = None
|
||||
self.edit_button: Optional[ttk.Button] = None
|
||||
self.delete_button: Optional[ttk.Button] = None
|
||||
self.selected: Optional[str] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
|
||||
|
@ -124,7 +124,7 @@ class HooksDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=lambda: self.destroy())
|
||||
button.grid(row=0, column=3, sticky="ew")
|
||||
|
||||
def click_create(self):
|
||||
def click_create(self) -> None:
|
||||
dialog = HookDialog(self, self.app)
|
||||
dialog.show()
|
||||
hook = dialog.hook
|
||||
|
@ -132,19 +132,19 @@ class HooksDialog(Dialog):
|
|||
self.app.core.hooks[hook.file] = hook
|
||||
self.listbox.insert(tk.END, hook.file)
|
||||
|
||||
def click_edit(self):
|
||||
def click_edit(self) -> None:
|
||||
hook = self.app.core.hooks[self.selected]
|
||||
dialog = HookDialog(self, self.app)
|
||||
dialog.set(hook)
|
||||
dialog.show()
|
||||
|
||||
def click_delete(self):
|
||||
def click_delete(self) -> None:
|
||||
del self.app.core.hooks[self.selected]
|
||||
self.listbox.delete(tk.ANCHOR)
|
||||
self.edit_button.config(state=tk.DISABLED)
|
||||
self.delete_button.config(state=tk.DISABLED)
|
||||
|
||||
def select(self, event: tk.Event):
|
||||
def select(self, event: tk.Event) -> None:
|
||||
if self.listbox.curselection():
|
||||
index = self.listbox.curselection()[0]
|
||||
self.selected = self.listbox.get(index)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
|
||||
import netaddr
|
||||
|
||||
|
@ -15,14 +15,14 @@ if TYPE_CHECKING:
|
|||
class IpConfigDialog(Dialog):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "IP Configuration")
|
||||
self.ip4 = self.app.guiconfig.ips.ip4
|
||||
self.ip6 = self.app.guiconfig.ips.ip6
|
||||
self.ip4s = self.app.guiconfig.ips.ip4s
|
||||
self.ip6s = self.app.guiconfig.ips.ip6s
|
||||
self.ip4_entry = None
|
||||
self.ip4_listbox = None
|
||||
self.ip6_entry = None
|
||||
self.ip6_listbox = None
|
||||
self.ip4: str = self.app.guiconfig.ips.ip4
|
||||
self.ip6: str = self.app.guiconfig.ips.ip6
|
||||
self.ip4s: List[str] = self.app.guiconfig.ips.ip4s
|
||||
self.ip6s: List[str] = self.app.guiconfig.ips.ip6s
|
||||
self.ip4_entry: Optional[ttk.Entry] = None
|
||||
self.ip4_listbox: Optional[ListboxScroll] = None
|
||||
self.ip6_entry: Optional[ttk.Entry] = None
|
||||
self.ip6_listbox: Optional[ListboxScroll] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self) -> None:
|
||||
|
|
|
@ -3,7 +3,7 @@ link configuration
|
|||
"""
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Union
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from core.gui import validation
|
||||
|
@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
|||
from core.gui.graph.graph import CanvasEdge
|
||||
|
||||
|
||||
def get_int(var: tk.StringVar) -> Union[int, None]:
|
||||
def get_int(var: tk.StringVar) -> Optional[int]:
|
||||
value = var.get()
|
||||
if value != "":
|
||||
return int(value)
|
||||
|
@ -24,7 +24,7 @@ def get_int(var: tk.StringVar) -> Union[int, None]:
|
|||
return None
|
||||
|
||||
|
||||
def get_float(var: tk.StringVar) -> Union[float, None]:
|
||||
def get_float(var: tk.StringVar) -> Optional[float]:
|
||||
value = var.get()
|
||||
if value != "":
|
||||
return float(value)
|
||||
|
@ -33,38 +33,39 @@ def get_float(var: tk.StringVar) -> Union[float, None]:
|
|||
|
||||
|
||||
class LinkConfigurationDialog(Dialog):
|
||||
def __init__(self, app: "Application", edge: "CanvasEdge"):
|
||||
def __init__(self, app: "Application", edge: "CanvasEdge") -> None:
|
||||
super().__init__(app, "Link Configuration")
|
||||
self.edge = edge
|
||||
self.is_symmetric = edge.link.options.unidirectional is False
|
||||
self.edge: "CanvasEdge" = edge
|
||||
self.is_symmetric: bool = edge.link.options.unidirectional is False
|
||||
if self.is_symmetric:
|
||||
self.symmetry_var = tk.StringVar(value=">>")
|
||||
symmetry_var = tk.StringVar(value=">>")
|
||||
else:
|
||||
self.symmetry_var = tk.StringVar(value="<<")
|
||||
symmetry_var = tk.StringVar(value="<<")
|
||||
self.symmetry_var: tk.StringVar = symmetry_var
|
||||
|
||||
self.bandwidth = tk.StringVar()
|
||||
self.delay = tk.StringVar()
|
||||
self.jitter = tk.StringVar()
|
||||
self.loss = tk.StringVar()
|
||||
self.duplicate = tk.StringVar()
|
||||
self.bandwidth: tk.StringVar = tk.StringVar()
|
||||
self.delay: tk.StringVar = tk.StringVar()
|
||||
self.jitter: tk.StringVar = tk.StringVar()
|
||||
self.loss: tk.StringVar = tk.StringVar()
|
||||
self.duplicate: tk.StringVar = tk.StringVar()
|
||||
|
||||
self.down_bandwidth = tk.StringVar()
|
||||
self.down_delay = tk.StringVar()
|
||||
self.down_jitter = tk.StringVar()
|
||||
self.down_loss = tk.StringVar()
|
||||
self.down_duplicate = tk.StringVar()
|
||||
self.down_bandwidth: tk.StringVar = tk.StringVar()
|
||||
self.down_delay: tk.StringVar = tk.StringVar()
|
||||
self.down_jitter: tk.StringVar = tk.StringVar()
|
||||
self.down_loss: tk.StringVar = tk.StringVar()
|
||||
self.down_duplicate: tk.StringVar = tk.StringVar()
|
||||
|
||||
self.color = tk.StringVar(value="#000000")
|
||||
self.color_button = None
|
||||
self.width = tk.DoubleVar()
|
||||
self.color: tk.StringVar = tk.StringVar(value="#000000")
|
||||
self.color_button: Optional[tk.Button] = None
|
||||
self.width: tk.DoubleVar = tk.DoubleVar()
|
||||
|
||||
self.load_link_config()
|
||||
self.symmetric_frame = None
|
||||
self.asymmetric_frame = None
|
||||
self.symmetric_frame: Optional[ttk.Frame] = None
|
||||
self.asymmetric_frame: Optional[ttk.Frame] = None
|
||||
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
source_name = self.app.canvas.nodes[self.edge.src].core_node.name
|
||||
dest_name = self.app.canvas.nodes[self.edge.dst].core_node.name
|
||||
|
@ -207,13 +208,13 @@ class LinkConfigurationDialog(Dialog):
|
|||
|
||||
return frame
|
||||
|
||||
def click_color(self):
|
||||
def click_color(self) -> None:
|
||||
dialog = ColorPickerDialog(self, self.app, self.color.get())
|
||||
color = dialog.askcolor()
|
||||
self.color.set(color)
|
||||
self.color_button.config(background=color)
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
self.app.canvas.itemconfigure(self.edge.id, width=self.width.get())
|
||||
self.app.canvas.itemconfigure(self.edge.id, fill=self.color.get())
|
||||
link = self.edge.link
|
||||
|
@ -288,7 +289,7 @@ class LinkConfigurationDialog(Dialog):
|
|||
|
||||
self.destroy()
|
||||
|
||||
def change_symmetry(self):
|
||||
def change_symmetry(self) -> None:
|
||||
if self.is_symmetric:
|
||||
self.is_symmetric = False
|
||||
self.symmetry_var.set("<<")
|
||||
|
@ -304,7 +305,7 @@ class LinkConfigurationDialog(Dialog):
|
|||
self.asymmetric_frame.grid_forget()
|
||||
self.symmetric_frame.grid(row=2, column=0)
|
||||
|
||||
def load_link_config(self):
|
||||
def load_link_config(self) -> None:
|
||||
"""
|
||||
populate link config to the table
|
||||
"""
|
||||
|
|
|
@ -15,7 +15,7 @@ class MacConfigDialog(Dialog):
|
|||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "MAC Configuration")
|
||||
mac = self.app.guiconfig.mac
|
||||
self.mac_var = tk.StringVar(value=mac)
|
||||
self.mac_var: tk.StringVar = tk.StringVar(value=mac)
|
||||
self.draw()
|
||||
|
||||
def draw(self) -> None:
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
mobility configuration
|
||||
"""
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc.common_pb2 import ConfigOption
|
||||
from core.api.grpc.core_pb2 import Node
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.themes import PADX, PADY
|
||||
from core.gui.widgets import ConfigFrame
|
||||
|
@ -16,23 +18,24 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class MobilityConfigDialog(Dialog):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode"):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
|
||||
super().__init__(app, f"{canvas_node.core_node.name} Mobility Configuration")
|
||||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.config_frame = None
|
||||
self.has_error = False
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node: Node = canvas_node.core_node
|
||||
self.config_frame: Optional[ConfigFrame] = None
|
||||
self.has_error: bool = False
|
||||
try:
|
||||
self.config = self.canvas_node.mobility_config
|
||||
if not self.config:
|
||||
self.config = self.app.core.get_mobility_config(self.node.id)
|
||||
config = self.canvas_node.mobility_config
|
||||
if not config:
|
||||
config = self.app.core.get_mobility_config(self.node.id)
|
||||
self.config: Dict[str, ConfigOption] = config
|
||||
self.draw()
|
||||
except grpc.RpcError as e:
|
||||
self.app.show_grpc_exception("Get Mobility Config Error", e)
|
||||
self.has_error = True
|
||||
self.has_error: bool = True
|
||||
self.destroy()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.config_frame = ConfigFrame(self.top, self.app, self.config)
|
||||
|
@ -40,7 +43,7 @@ class MobilityConfigDialog(Dialog):
|
|||
self.config_frame.grid(sticky="nsew", pady=PADY)
|
||||
self.draw_apply_buttons()
|
||||
|
||||
def draw_apply_buttons(self):
|
||||
def draw_apply_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -52,7 +55,7 @@ class MobilityConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
self.config_frame.parse_config()
|
||||
self.canvas_node.mobility_config = self.config
|
||||
self.destroy()
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc.common_pb2 import ConfigOption
|
||||
from core.api.grpc.core_pb2 import Node
|
||||
from core.api.grpc.mobility_pb2 import MobilityAction
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.images import ImageEnum
|
||||
|
@ -13,18 +15,23 @@ if TYPE_CHECKING:
|
|||
from core.gui.app import Application
|
||||
from core.gui.graph.node import CanvasNode
|
||||
|
||||
ICON_SIZE = 16
|
||||
ICON_SIZE: int = 16
|
||||
|
||||
|
||||
class MobilityPlayer:
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode", config):
|
||||
self.app = app
|
||||
self.canvas_node = canvas_node
|
||||
self.config = config
|
||||
self.dialog = None
|
||||
self.state = None
|
||||
def __init__(
|
||||
self,
|
||||
app: "Application",
|
||||
canvas_node: "CanvasNode",
|
||||
config: Dict[str, ConfigOption],
|
||||
) -> None:
|
||||
self.app: "Application" = app
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.config: Dict[str, ConfigOption] = config
|
||||
self.dialog: Optional[MobilityPlayerDialog] = None
|
||||
self.state: Optional[MobilityAction] = None
|
||||
|
||||
def show(self):
|
||||
def show(self) -> None:
|
||||
if self.dialog:
|
||||
self.dialog.destroy()
|
||||
self.dialog = MobilityPlayerDialog(self.app, self.canvas_node, self.config)
|
||||
|
@ -37,44 +44,49 @@ class MobilityPlayer:
|
|||
self.set_stop()
|
||||
self.dialog.show()
|
||||
|
||||
def close(self):
|
||||
def close(self) -> None:
|
||||
if self.dialog:
|
||||
self.dialog.destroy()
|
||||
self.dialog = None
|
||||
|
||||
def set_play(self):
|
||||
def set_play(self) -> None:
|
||||
self.state = MobilityAction.START
|
||||
if self.dialog:
|
||||
self.dialog.set_play()
|
||||
|
||||
def set_pause(self):
|
||||
def set_pause(self) -> None:
|
||||
self.state = MobilityAction.PAUSE
|
||||
if self.dialog:
|
||||
self.dialog.set_pause()
|
||||
|
||||
def set_stop(self):
|
||||
def set_stop(self) -> None:
|
||||
self.state = MobilityAction.STOP
|
||||
if self.dialog:
|
||||
self.dialog.set_stop()
|
||||
|
||||
|
||||
class MobilityPlayerDialog(Dialog):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode", config):
|
||||
def __init__(
|
||||
self,
|
||||
app: "Application",
|
||||
canvas_node: "CanvasNode",
|
||||
config: Dict[str, ConfigOption],
|
||||
) -> None:
|
||||
super().__init__(
|
||||
app, f"{canvas_node.core_node.name} Mobility Player", modal=False
|
||||
)
|
||||
self.resizable(False, False)
|
||||
self.geometry("")
|
||||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.config = config
|
||||
self.play_button = None
|
||||
self.pause_button = None
|
||||
self.stop_button = None
|
||||
self.progressbar = None
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node: Node = canvas_node.core_node
|
||||
self.config: Dict[str, ConfigOption] = config
|
||||
self.play_button: Optional[ttk.Button] = None
|
||||
self.pause_button: Optional[ttk.Button] = None
|
||||
self.stop_button: Optional[ttk.Button] = None
|
||||
self.progressbar: Optional[ttk.Progressbar] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
|
||||
file_name = self.config["file"].value
|
||||
|
@ -114,27 +126,27 @@ class MobilityPlayerDialog(Dialog):
|
|||
label = ttk.Label(frame, text=f"rate {rate} ms")
|
||||
label.grid(row=0, column=4)
|
||||
|
||||
def clear_buttons(self):
|
||||
def clear_buttons(self) -> None:
|
||||
self.play_button.state(["!pressed"])
|
||||
self.pause_button.state(["!pressed"])
|
||||
self.stop_button.state(["!pressed"])
|
||||
|
||||
def set_play(self):
|
||||
def set_play(self) -> None:
|
||||
self.clear_buttons()
|
||||
self.play_button.state(["pressed"])
|
||||
self.progressbar.start()
|
||||
|
||||
def set_pause(self):
|
||||
def set_pause(self) -> None:
|
||||
self.clear_buttons()
|
||||
self.pause_button.state(["pressed"])
|
||||
self.progressbar.stop()
|
||||
|
||||
def set_stop(self):
|
||||
def set_stop(self) -> None:
|
||||
self.clear_buttons()
|
||||
self.stop_button.state(["pressed"])
|
||||
self.progressbar.stop()
|
||||
|
||||
def click_play(self):
|
||||
def click_play(self) -> None:
|
||||
self.set_play()
|
||||
session_id = self.app.core.session_id
|
||||
try:
|
||||
|
@ -144,7 +156,7 @@ class MobilityPlayerDialog(Dialog):
|
|||
except grpc.RpcError as e:
|
||||
self.app.show_grpc_exception("Mobility Error", e)
|
||||
|
||||
def click_pause(self):
|
||||
def click_pause(self) -> None:
|
||||
self.set_pause()
|
||||
session_id = self.app.core.session_id
|
||||
try:
|
||||
|
@ -154,7 +166,7 @@ class MobilityPlayerDialog(Dialog):
|
|||
except grpc.RpcError as e:
|
||||
self.app.show_grpc_exception("Mobility Error", e)
|
||||
|
||||
def click_stop(self):
|
||||
def click_stop(self) -> None:
|
||||
self.set_stop()
|
||||
session_id = self.app.core.session_id
|
||||
try:
|
||||
|
|
|
@ -2,10 +2,12 @@ import logging
|
|||
import tkinter as tk
|
||||
from functools import partial
|
||||
from tkinter import messagebox, ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
import netaddr
|
||||
from PIL.ImageTk import PhotoImage
|
||||
|
||||
from core.api.grpc.core_pb2 import Node
|
||||
from core.gui import nodeutils, validation
|
||||
from core.gui.appconfig import ICONS_PATH
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -86,35 +88,35 @@ class InterfaceData:
|
|||
mac: tk.StringVar,
|
||||
ip4: tk.StringVar,
|
||||
ip6: tk.StringVar,
|
||||
):
|
||||
self.is_auto = is_auto
|
||||
self.mac = mac
|
||||
self.ip4 = ip4
|
||||
self.ip6 = ip6
|
||||
) -> None:
|
||||
self.is_auto: tk.BooleanVar = is_auto
|
||||
self.mac: tk.StringVar = mac
|
||||
self.ip4: tk.StringVar = ip4
|
||||
self.ip6: tk.StringVar = ip6
|
||||
|
||||
|
||||
class NodeConfigDialog(Dialog):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode"):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
|
||||
"""
|
||||
create an instance of node configuration
|
||||
"""
|
||||
super().__init__(app, f"{canvas_node.core_node.name} Configuration")
|
||||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.image = canvas_node.image
|
||||
self.image_file = None
|
||||
self.image_button = None
|
||||
self.name = tk.StringVar(value=self.node.name)
|
||||
self.type = tk.StringVar(value=self.node.model)
|
||||
self.container_image = tk.StringVar(value=self.node.image)
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node: Node = canvas_node.core_node
|
||||
self.image: PhotoImage = canvas_node.image
|
||||
self.image_file: Optional[str] = None
|
||||
self.image_button: Optional[ttk.Button] = None
|
||||
self.name: tk.StringVar = tk.StringVar(value=self.node.name)
|
||||
self.type: tk.StringVar = tk.StringVar(value=self.node.model)
|
||||
self.container_image: tk.StringVar = tk.StringVar(value=self.node.image)
|
||||
server = "localhost"
|
||||
if self.node.server:
|
||||
server = self.node.server
|
||||
self.server = tk.StringVar(value=server)
|
||||
self.ifaces = {}
|
||||
self.server: tk.StringVar = tk.StringVar(value=server)
|
||||
self.ifaces: Dict[int, InterfaceData] = {}
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
row = 0
|
||||
|
||||
|
@ -202,7 +204,7 @@ class NodeConfigDialog(Dialog):
|
|||
self.draw_spacer()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_ifaces(self):
|
||||
def draw_ifaces(self) -> None:
|
||||
notebook = ttk.Notebook(self.top)
|
||||
notebook.grid(sticky="nsew", pady=PADY)
|
||||
self.top.rowconfigure(notebook.grid_info()["row"], weight=1)
|
||||
|
@ -265,7 +267,7 @@ class NodeConfigDialog(Dialog):
|
|||
|
||||
self.ifaces[iface.id] = InterfaceData(is_auto, mac, ip4, ip6)
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
frame.columnconfigure(0, weight=1)
|
||||
|
@ -277,20 +279,20 @@ class NodeConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_emane_config(self, emane_model: str, iface_id: int):
|
||||
def click_emane_config(self, emane_model: str, iface_id: int) -> None:
|
||||
dialog = EmaneModelDialog(
|
||||
self, self.app, self.canvas_node, emane_model, iface_id
|
||||
)
|
||||
dialog.show()
|
||||
|
||||
def click_icon(self):
|
||||
def click_icon(self) -> None:
|
||||
file_path = image_chooser(self, ICONS_PATH)
|
||||
if file_path:
|
||||
self.image = Images.create(file_path, nodeutils.ICON_SIZE)
|
||||
self.image_button.config(image=self.image)
|
||||
self.image_file = file_path
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
error = False
|
||||
|
||||
# update core node
|
||||
|
@ -354,7 +356,7 @@ class NodeConfigDialog(Dialog):
|
|||
self.canvas_node.redraw()
|
||||
self.destroy()
|
||||
|
||||
def iface_select(self, event: tk.Event):
|
||||
def iface_select(self, event: tk.Event) -> None:
|
||||
listbox = event.widget
|
||||
cur = listbox.curselection()
|
||||
if cur:
|
||||
|
|
|
@ -4,7 +4,7 @@ core node services
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
from typing import TYPE_CHECKING, Set
|
||||
from typing import TYPE_CHECKING, Optional, Set
|
||||
|
||||
from core.gui.dialogs.configserviceconfig import ConfigServiceConfigDialog
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -19,20 +19,20 @@ if TYPE_CHECKING:
|
|||
class NodeConfigServiceDialog(Dialog):
|
||||
def __init__(
|
||||
self, app: "Application", canvas_node: "CanvasNode", services: Set[str] = None
|
||||
):
|
||||
) -> None:
|
||||
title = f"{canvas_node.core_node.name} Config Services"
|
||||
super().__init__(app, title)
|
||||
self.canvas_node = canvas_node
|
||||
self.node_id = canvas_node.core_node.id
|
||||
self.groups = None
|
||||
self.services = None
|
||||
self.current = None
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node_id: int = canvas_node.core_node.id
|
||||
self.groups: Optional[ListboxScroll] = None
|
||||
self.services: Optional[CheckboxList] = None
|
||||
self.current: Optional[ListboxScroll] = None
|
||||
if services is None:
|
||||
services = set(canvas_node.core_node.config_services)
|
||||
self.current_services = services
|
||||
self.current_services: Set[str] = services
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
|
||||
|
@ -86,7 +86,7 @@ class NodeConfigServiceDialog(Dialog):
|
|||
# trigger group change
|
||||
self.groups.listbox.event_generate("<<ListboxSelect>>")
|
||||
|
||||
def handle_group_change(self, event: tk.Event = None):
|
||||
def handle_group_change(self, event: tk.Event = None) -> None:
|
||||
selection = self.groups.listbox.curselection()
|
||||
if selection:
|
||||
index = selection[0]
|
||||
|
@ -96,7 +96,7 @@ class NodeConfigServiceDialog(Dialog):
|
|||
checked = name in self.current_services
|
||||
self.services.add(name, checked)
|
||||
|
||||
def service_clicked(self, name: str, var: tk.IntVar):
|
||||
def service_clicked(self, name: str, var: tk.IntVar) -> None:
|
||||
if var.get() and name not in self.current_services:
|
||||
self.current_services.add(name)
|
||||
elif not var.get() and name in self.current_services:
|
||||
|
@ -104,7 +104,7 @@ class NodeConfigServiceDialog(Dialog):
|
|||
self.draw_current_services()
|
||||
self.canvas_node.core_node.config_services[:] = self.current_services
|
||||
|
||||
def click_configure(self):
|
||||
def click_configure(self) -> None:
|
||||
current_selection = self.current.listbox.curselection()
|
||||
if len(current_selection):
|
||||
dialog = ConfigServiceConfigDialog(
|
||||
|
@ -124,25 +124,25 @@ class NodeConfigServiceDialog(Dialog):
|
|||
parent=self,
|
||||
)
|
||||
|
||||
def draw_current_services(self):
|
||||
def draw_current_services(self) -> None:
|
||||
self.current.listbox.delete(0, tk.END)
|
||||
for name in sorted(self.current_services):
|
||||
self.current.listbox.insert(tk.END, name)
|
||||
if self.is_custom_service(name):
|
||||
self.current.listbox.itemconfig(tk.END, bg="green")
|
||||
|
||||
def click_save(self):
|
||||
def click_save(self) -> None:
|
||||
self.canvas_node.core_node.config_services[:] = self.current_services
|
||||
logging.info(
|
||||
"saved node config services: %s", self.canvas_node.core_node.config_services
|
||||
)
|
||||
self.destroy()
|
||||
|
||||
def click_cancel(self):
|
||||
def click_cancel(self) -> None:
|
||||
self.current_services = None
|
||||
self.destroy()
|
||||
|
||||
def click_remove(self):
|
||||
def click_remove(self) -> None:
|
||||
cur = self.current.listbox.curselection()
|
||||
if cur:
|
||||
service = self.current.listbox.get(cur[0])
|
||||
|
|
|
@ -3,7 +3,7 @@ core node services
|
|||
"""
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional, Set
|
||||
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.dialogs.serviceconfig import ServiceConfigDialog
|
||||
|
@ -16,19 +16,19 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class NodeServiceDialog(Dialog):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode"):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
|
||||
title = f"{canvas_node.core_node.name} Services"
|
||||
super().__init__(app, title)
|
||||
self.canvas_node = canvas_node
|
||||
self.node_id = canvas_node.core_node.id
|
||||
self.groups = None
|
||||
self.services = None
|
||||
self.current = None
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node_id: int = canvas_node.core_node.id
|
||||
self.groups: Optional[ListboxScroll] = None
|
||||
self.services: Optional[CheckboxList] = None
|
||||
self.current: Optional[ListboxScroll] = None
|
||||
services = set(canvas_node.core_node.services)
|
||||
self.current_services = services
|
||||
self.current_services: Set[str] = services
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
|
||||
|
@ -84,7 +84,7 @@ class NodeServiceDialog(Dialog):
|
|||
# trigger group change
|
||||
self.groups.listbox.event_generate("<<ListboxSelect>>")
|
||||
|
||||
def handle_group_change(self, event: tk.Event = None):
|
||||
def handle_group_change(self, event: tk.Event = None) -> None:
|
||||
selection = self.groups.listbox.curselection()
|
||||
if selection:
|
||||
index = selection[0]
|
||||
|
@ -94,7 +94,7 @@ class NodeServiceDialog(Dialog):
|
|||
checked = name in self.current_services
|
||||
self.services.add(name, checked)
|
||||
|
||||
def service_clicked(self, name: str, var: tk.IntVar):
|
||||
def service_clicked(self, name: str, var: tk.IntVar) -> None:
|
||||
if var.get() and name not in self.current_services:
|
||||
self.current_services.add(name)
|
||||
elif not var.get() and name in self.current_services:
|
||||
|
@ -106,7 +106,7 @@ class NodeServiceDialog(Dialog):
|
|||
self.current.listbox.itemconfig(tk.END, bg="green")
|
||||
self.canvas_node.core_node.services[:] = self.current_services
|
||||
|
||||
def click_configure(self):
|
||||
def click_configure(self) -> None:
|
||||
current_selection = self.current.listbox.curselection()
|
||||
if len(current_selection):
|
||||
dialog = ServiceConfigDialog(
|
||||
|
@ -127,12 +127,12 @@ class NodeServiceDialog(Dialog):
|
|||
"Service Configuration", "Select a service to configure", parent=self
|
||||
)
|
||||
|
||||
def click_save(self):
|
||||
def click_save(self) -> None:
|
||||
core_node = self.canvas_node.core_node
|
||||
core_node.services[:] = self.current_services
|
||||
self.destroy()
|
||||
|
||||
def click_remove(self):
|
||||
def click_remove(self) -> None:
|
||||
cur = self.current.listbox.curselection()
|
||||
if cur:
|
||||
service = self.current.listbox.get(cur[0])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.gui.appconfig import Observer
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -12,18 +12,18 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class ObserverDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Observer Widgets")
|
||||
self.observers = None
|
||||
self.save_button = None
|
||||
self.delete_button = None
|
||||
self.selected = None
|
||||
self.selected_index = None
|
||||
self.name = tk.StringVar()
|
||||
self.cmd = tk.StringVar()
|
||||
self.observers: Optional[tk.Listbox] = None
|
||||
self.save_button: Optional[ttk.Button] = None
|
||||
self.delete_button: Optional[ttk.Button] = None
|
||||
self.selected: Optional[str] = None
|
||||
self.selected_index: Optional[int] = None
|
||||
self.name: tk.StringVar = tk.StringVar()
|
||||
self.cmd: tk.StringVar = tk.StringVar()
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.draw_listbox()
|
||||
|
@ -31,7 +31,7 @@ class ObserverDialog(Dialog):
|
|||
self.draw_config_buttons()
|
||||
self.draw_apply_buttons()
|
||||
|
||||
def draw_listbox(self):
|
||||
def draw_listbox(self) -> None:
|
||||
listbox_scroll = ListboxScroll(self.top)
|
||||
listbox_scroll.grid(sticky="nsew", pady=PADY)
|
||||
listbox_scroll.columnconfigure(0, weight=1)
|
||||
|
@ -42,7 +42,7 @@ class ObserverDialog(Dialog):
|
|||
for name in sorted(self.app.core.custom_observers):
|
||||
self.observers.insert(tk.END, name)
|
||||
|
||||
def draw_form_fields(self):
|
||||
def draw_form_fields(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew", pady=PADY)
|
||||
frame.columnconfigure(1, weight=1)
|
||||
|
@ -57,7 +57,7 @@ class ObserverDialog(Dialog):
|
|||
entry = ttk.Entry(frame, textvariable=self.cmd)
|
||||
entry.grid(row=1, column=1, sticky="ew")
|
||||
|
||||
def draw_config_buttons(self):
|
||||
def draw_config_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew", pady=PADY)
|
||||
for i in range(3):
|
||||
|
@ -76,7 +76,7 @@ class ObserverDialog(Dialog):
|
|||
)
|
||||
self.delete_button.grid(row=0, column=2, sticky="ew")
|
||||
|
||||
def draw_apply_buttons(self):
|
||||
def draw_apply_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -88,14 +88,14 @@ class ObserverDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_save_config(self):
|
||||
def click_save_config(self) -> None:
|
||||
self.app.guiconfig.observers.clear()
|
||||
for observer in self.app.core.custom_observers.values():
|
||||
self.app.guiconfig.observers.append(observer)
|
||||
self.app.save_config()
|
||||
self.destroy()
|
||||
|
||||
def click_create(self):
|
||||
def click_create(self) -> None:
|
||||
name = self.name.get()
|
||||
if name not in self.app.core.custom_observers:
|
||||
cmd = self.cmd.get()
|
||||
|
@ -109,7 +109,7 @@ class ObserverDialog(Dialog):
|
|||
else:
|
||||
messagebox.showerror("Observer Error", f"{name} already exists")
|
||||
|
||||
def click_save(self):
|
||||
def click_save(self) -> None:
|
||||
name = self.name.get()
|
||||
if self.selected:
|
||||
previous_name = self.selected
|
||||
|
@ -122,7 +122,7 @@ class ObserverDialog(Dialog):
|
|||
self.observers.insert(self.selected_index, name)
|
||||
self.observers.selection_set(self.selected_index)
|
||||
|
||||
def click_delete(self):
|
||||
def click_delete(self) -> None:
|
||||
if self.selected:
|
||||
self.observers.delete(self.selected_index)
|
||||
del self.app.core.custom_observers[self.selected]
|
||||
|
@ -136,7 +136,7 @@ class ObserverDialog(Dialog):
|
|||
self.app.menubar.observers_menu.draw_custom()
|
||||
self.app.toolbar.observers_menu.draw_custom()
|
||||
|
||||
def handle_observer_change(self, event: tk.Event):
|
||||
def handle_observer_change(self, event: tk.Event) -> None:
|
||||
selection = self.observers.curselection()
|
||||
if selection:
|
||||
self.selected_index = selection[0]
|
||||
|
|
|
@ -12,27 +12,27 @@ from core.gui.validation import LARGEST_SCALE, SMALLEST_SCALE
|
|||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
|
||||
SCALE_INTERVAL = 0.01
|
||||
SCALE_INTERVAL: float = 0.01
|
||||
|
||||
|
||||
class PreferencesDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Preferences")
|
||||
self.gui_scale = tk.DoubleVar(value=self.app.app_scale)
|
||||
self.gui_scale: tk.DoubleVar = tk.DoubleVar(value=self.app.app_scale)
|
||||
preferences = self.app.guiconfig.preferences
|
||||
self.editor = tk.StringVar(value=preferences.editor)
|
||||
self.theme = tk.StringVar(value=preferences.theme)
|
||||
self.terminal = tk.StringVar(value=preferences.terminal)
|
||||
self.gui3d = tk.StringVar(value=preferences.gui3d)
|
||||
self.editor: tk.StringVar = tk.StringVar(value=preferences.editor)
|
||||
self.theme: tk.StringVar = tk.StringVar(value=preferences.theme)
|
||||
self.terminal: tk.StringVar = tk.StringVar(value=preferences.terminal)
|
||||
self.gui3d: tk.StringVar = tk.StringVar(value=preferences.gui3d)
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.draw_preferences()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_preferences(self):
|
||||
def draw_preferences(self) -> None:
|
||||
frame = ttk.LabelFrame(self.top, text="Preferences", padding=FRAME_PAD)
|
||||
frame.grid(sticky="nsew", pady=PADY)
|
||||
frame.columnconfigure(1, weight=1)
|
||||
|
@ -88,7 +88,7 @@ class PreferencesDialog(Dialog):
|
|||
scrollbar = ttk.Scrollbar(scale_frame, command=self.adjust_scale)
|
||||
scrollbar.grid(row=0, column=2)
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -100,12 +100,12 @@ class PreferencesDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def theme_change(self, event: tk.Event):
|
||||
def theme_change(self, event: tk.Event) -> None:
|
||||
theme = self.theme.get()
|
||||
logging.info("changing theme: %s", theme)
|
||||
self.app.style.theme_use(theme)
|
||||
|
||||
def click_save(self):
|
||||
def click_save(self) -> None:
|
||||
preferences = self.app.guiconfig.preferences
|
||||
preferences.terminal = self.terminal.get()
|
||||
preferences.editor = self.editor.get()
|
||||
|
@ -118,7 +118,7 @@ class PreferencesDialog(Dialog):
|
|||
self.scale_adjust()
|
||||
self.destroy()
|
||||
|
||||
def scale_adjust(self):
|
||||
def scale_adjust(self) -> None:
|
||||
app_scale = self.gui_scale.get()
|
||||
self.app.app_scale = app_scale
|
||||
self.app.master.tk.call("tk", "scaling", app_scale)
|
||||
|
@ -136,7 +136,7 @@ class PreferencesDialog(Dialog):
|
|||
self.app.toolbar.scale()
|
||||
self.app.canvas.scale_graph()
|
||||
|
||||
def adjust_scale(self, arg1: str, arg2: str, arg3: str):
|
||||
def adjust_scale(self, arg1: str, arg2: str, arg3: str) -> None:
|
||||
scale_value = self.gui_scale.get()
|
||||
if arg2 == "-1":
|
||||
if scale_value <= LARGEST_SCALE - SCALE_INTERVAL:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.nodeutils import NodeUtils
|
||||
|
@ -14,10 +14,10 @@ if TYPE_CHECKING:
|
|||
class RunToolDialog(Dialog):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Run Tool")
|
||||
self.cmd = tk.StringVar(value="ps ax")
|
||||
self.result = None
|
||||
self.node_list = None
|
||||
self.executable_nodes = {}
|
||||
self.cmd: tk.StringVar = tk.StringVar(value="ps ax")
|
||||
self.result: Optional[CodeText] = None
|
||||
self.node_list: Optional[ListboxScroll] = None
|
||||
self.executable_nodes: Dict[str, int] = {}
|
||||
self.store_nodes()
|
||||
self.draw()
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.gui.appconfig import CoreServer
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -10,24 +10,24 @@ from core.gui.widgets import ListboxScroll
|
|||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
|
||||
DEFAULT_NAME = "example"
|
||||
DEFAULT_ADDRESS = "127.0.0.1"
|
||||
DEFAULT_PORT = 50051
|
||||
DEFAULT_NAME: str = "example"
|
||||
DEFAULT_ADDRESS: str = "127.0.0.1"
|
||||
DEFAULT_PORT: int = 50051
|
||||
|
||||
|
||||
class ServersDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "CORE Servers")
|
||||
self.name = tk.StringVar(value=DEFAULT_NAME)
|
||||
self.address = tk.StringVar(value=DEFAULT_ADDRESS)
|
||||
self.servers = None
|
||||
self.selected_index = None
|
||||
self.selected = None
|
||||
self.save_button = None
|
||||
self.delete_button = None
|
||||
self.name: tk.StringVar = tk.StringVar(value=DEFAULT_NAME)
|
||||
self.address: tk.StringVar = tk.StringVar(value=DEFAULT_ADDRESS)
|
||||
self.servers: Optional[tk.Listbox] = None
|
||||
self.selected_index: Optional[int] = None
|
||||
self.selected: Optional[str] = None
|
||||
self.save_button: Optional[ttk.Button] = None
|
||||
self.delete_button: Optional[ttk.Button] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.draw_servers()
|
||||
|
@ -35,7 +35,7 @@ class ServersDialog(Dialog):
|
|||
self.draw_server_configuration()
|
||||
self.draw_apply_buttons()
|
||||
|
||||
def draw_servers(self):
|
||||
def draw_servers(self) -> None:
|
||||
listbox_scroll = ListboxScroll(self.top)
|
||||
listbox_scroll.grid(pady=PADY, sticky="nsew")
|
||||
listbox_scroll.columnconfigure(0, weight=1)
|
||||
|
@ -48,7 +48,7 @@ class ServersDialog(Dialog):
|
|||
for server in self.app.core.servers:
|
||||
self.servers.insert(tk.END, server)
|
||||
|
||||
def draw_server_configuration(self):
|
||||
def draw_server_configuration(self) -> None:
|
||||
frame = ttk.LabelFrame(self.top, text="Server Configuration", padding=FRAME_PAD)
|
||||
frame.grid(pady=PADY, sticky="ew")
|
||||
frame.columnconfigure(1, weight=1)
|
||||
|
@ -64,7 +64,7 @@ class ServersDialog(Dialog):
|
|||
entry = ttk.Entry(frame, textvariable=self.address)
|
||||
entry.grid(row=0, column=3, sticky="ew")
|
||||
|
||||
def draw_servers_buttons(self):
|
||||
def draw_servers_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(pady=PADY, sticky="ew")
|
||||
for i in range(3):
|
||||
|
@ -83,7 +83,7 @@ class ServersDialog(Dialog):
|
|||
)
|
||||
self.delete_button.grid(row=0, column=2, sticky="ew")
|
||||
|
||||
def draw_apply_buttons(self):
|
||||
def draw_apply_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(2):
|
||||
|
@ -104,7 +104,7 @@ class ServersDialog(Dialog):
|
|||
self.app.save_config()
|
||||
self.destroy()
|
||||
|
||||
def click_create(self):
|
||||
def click_create(self) -> None:
|
||||
name = self.name.get()
|
||||
if name not in self.app.core.servers:
|
||||
address = self.address.get()
|
||||
|
@ -112,7 +112,7 @@ class ServersDialog(Dialog):
|
|||
self.app.core.servers[name] = server
|
||||
self.servers.insert(tk.END, name)
|
||||
|
||||
def click_save(self):
|
||||
def click_save(self) -> None:
|
||||
name = self.name.get()
|
||||
if self.selected:
|
||||
previous_name = self.selected
|
||||
|
@ -125,7 +125,7 @@ class ServersDialog(Dialog):
|
|||
self.servers.insert(self.selected_index, name)
|
||||
self.servers.selection_set(self.selected_index)
|
||||
|
||||
def click_delete(self):
|
||||
def click_delete(self) -> None:
|
||||
if self.selected:
|
||||
self.servers.delete(self.selected_index)
|
||||
del self.app.core.servers[self.selected]
|
||||
|
@ -137,7 +137,7 @@ class ServersDialog(Dialog):
|
|||
self.save_button.config(state=tk.DISABLED)
|
||||
self.delete_button.config(state=tk.DISABLED)
|
||||
|
||||
def handle_server_change(self, event: tk.Event):
|
||||
def handle_server_change(self, event: tk.Event) -> None:
|
||||
selection = self.servers.curselection()
|
||||
if selection:
|
||||
self.selected_index = selection[0]
|
||||
|
|
|
@ -2,11 +2,12 @@ import logging
|
|||
import os
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog, ttk
|
||||
from typing import TYPE_CHECKING, List
|
||||
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple
|
||||
|
||||
import grpc
|
||||
from PIL.ImageTk import PhotoImage
|
||||
|
||||
from core.api.grpc.services_pb2 import ServiceValidationMode
|
||||
from core.api.grpc.services_pb2 import NodeServiceData, ServiceValidationMode
|
||||
from core.gui.dialogs.copyserviceconfig import CopyServiceConfigDialog
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.images import ImageEnum, Images
|
||||
|
@ -16,8 +17,9 @@ from core.gui.widgets import CodeText, ListboxScroll
|
|||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
from core.gui.graph.node import CanvasNode
|
||||
from core.gui.coreclient import CoreClient
|
||||
|
||||
ICON_SIZE = 16
|
||||
ICON_SIZE: int = 16
|
||||
|
||||
|
||||
class ServiceConfigDialog(Dialog):
|
||||
|
@ -28,54 +30,57 @@ class ServiceConfigDialog(Dialog):
|
|||
service_name: str,
|
||||
canvas_node: "CanvasNode",
|
||||
node_id: int,
|
||||
):
|
||||
) -> None:
|
||||
title = f"{service_name} Service"
|
||||
super().__init__(app, title, master=master)
|
||||
self.core = app.core
|
||||
self.canvas_node = canvas_node
|
||||
self.node_id = node_id
|
||||
self.service_name = service_name
|
||||
self.radiovar = tk.IntVar()
|
||||
self.radiovar.set(2)
|
||||
self.metadata = ""
|
||||
self.filenames = []
|
||||
self.dependencies = []
|
||||
self.executables = []
|
||||
self.startup_commands = []
|
||||
self.validation_commands = []
|
||||
self.shutdown_commands = []
|
||||
self.default_startup = []
|
||||
self.default_validate = []
|
||||
self.default_shutdown = []
|
||||
self.validation_mode = None
|
||||
self.validation_time = None
|
||||
self.validation_period = None
|
||||
self.directory_entry = None
|
||||
self.default_directories = []
|
||||
self.temp_directories = []
|
||||
self.documentnew_img = self.app.get_icon(ImageEnum.DOCUMENTNEW, ICON_SIZE)
|
||||
self.editdelete_img = self.app.get_icon(ImageEnum.EDITDELETE, ICON_SIZE)
|
||||
self.notebook = None
|
||||
self.metadata_entry = None
|
||||
self.filename_combobox = None
|
||||
self.dir_list = None
|
||||
self.startup_commands_listbox = None
|
||||
self.shutdown_commands_listbox = None
|
||||
self.validate_commands_listbox = None
|
||||
self.validation_time_entry = None
|
||||
self.validation_mode_entry = None
|
||||
self.service_file_data = None
|
||||
self.validation_period_entry = None
|
||||
self.original_service_files = {}
|
||||
self.default_config = None
|
||||
self.temp_service_files = {}
|
||||
self.modified_files = set()
|
||||
self.has_error = False
|
||||
self.core: "CoreClient" = app.core
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node_id: int = node_id
|
||||
self.service_name: str = service_name
|
||||
self.radiovar: tk.IntVar = tk.IntVar(value=2)
|
||||
self.metadata: str = ""
|
||||
self.filenames: List[str] = []
|
||||
self.dependencies: List[str] = []
|
||||
self.executables: List[str] = []
|
||||
self.startup_commands: List[str] = []
|
||||
self.validation_commands: List[str] = []
|
||||
self.shutdown_commands: List[str] = []
|
||||
self.default_startup: List[str] = []
|
||||
self.default_validate: List[str] = []
|
||||
self.default_shutdown: List[str] = []
|
||||
self.validation_mode: Optional[ServiceValidationMode] = None
|
||||
self.validation_time: Optional[int] = None
|
||||
self.validation_period: Optional[float] = None
|
||||
self.directory_entry: Optional[ttk.Entry] = None
|
||||
self.default_directories: List[str] = []
|
||||
self.temp_directories: List[str] = []
|
||||
self.documentnew_img: PhotoImage = self.app.get_icon(
|
||||
ImageEnum.DOCUMENTNEW, ICON_SIZE
|
||||
)
|
||||
self.editdelete_img: PhotoImage = self.app.get_icon(
|
||||
ImageEnum.EDITDELETE, ICON_SIZE
|
||||
)
|
||||
self.notebook: Optional[ttk.Notebook] = None
|
||||
self.metadata_entry: Optional[ttk.Entry] = None
|
||||
self.filename_combobox: Optional[ttk.Combobox] = None
|
||||
self.dir_list: Optional[ListboxScroll] = None
|
||||
self.startup_commands_listbox: Optional[tk.Listbox] = None
|
||||
self.shutdown_commands_listbox: Optional[tk.Listbox] = None
|
||||
self.validate_commands_listbox: Optional[tk.Listbox] = None
|
||||
self.validation_time_entry: Optional[ttk.Entry] = None
|
||||
self.validation_mode_entry: Optional[ttk.Entry] = None
|
||||
self.service_file_data: Optional[CodeText] = None
|
||||
self.validation_period_entry: Optional[ttk.Entry] = None
|
||||
self.original_service_files: Dict[str, str] = {}
|
||||
self.default_config: NodeServiceData = None
|
||||
self.temp_service_files: Dict[str, str] = {}
|
||||
self.modified_files: Set[str] = set()
|
||||
self.has_error: bool = False
|
||||
self.load()
|
||||
if not self.has_error:
|
||||
self.draw()
|
||||
|
||||
def load(self):
|
||||
def load(self) -> None:
|
||||
try:
|
||||
self.app.core.create_nodes_and_links()
|
||||
default_config = self.app.core.get_node_service(
|
||||
|
@ -119,7 +124,7 @@ class ServiceConfigDialog(Dialog):
|
|||
self.app.show_grpc_exception("Get Node Service Error", e)
|
||||
self.has_error = True
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(1, weight=1)
|
||||
|
||||
|
@ -142,7 +147,7 @@ class ServiceConfigDialog(Dialog):
|
|||
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_tab_files(self):
|
||||
def draw_tab_files(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="nsew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -222,7 +227,7 @@ class ServiceConfigDialog(Dialog):
|
|||
"<FocusOut>", self.update_temp_service_file_data
|
||||
)
|
||||
|
||||
def draw_tab_directories(self):
|
||||
def draw_tab_directories(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="nsew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -257,7 +262,7 @@ class ServiceConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Remove", command=self.remove_directory)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def draw_tab_startstop(self):
|
||||
def draw_tab_startstop(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="nsew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -311,7 +316,7 @@ class ServiceConfigDialog(Dialog):
|
|||
elif i == 2:
|
||||
self.validate_commands_listbox = listbox_scroll.listbox
|
||||
|
||||
def draw_tab_configuration(self):
|
||||
def draw_tab_configuration(self) -> None:
|
||||
tab = ttk.Frame(self.notebook, padding=FRAME_PAD)
|
||||
tab.grid(sticky="nsew")
|
||||
tab.columnconfigure(0, weight=1)
|
||||
|
@ -370,7 +375,7 @@ class ServiceConfigDialog(Dialog):
|
|||
for dependency in self.dependencies:
|
||||
listbox_scroll.listbox.insert("end", dependency)
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="ew")
|
||||
for i in range(4):
|
||||
|
@ -384,7 +389,7 @@ class ServiceConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=3, sticky="ew")
|
||||
|
||||
def add_filename(self):
|
||||
def add_filename(self) -> None:
|
||||
filename = self.filename_combobox.get()
|
||||
if filename not in self.filename_combobox["values"]:
|
||||
self.filename_combobox["values"] += (filename,)
|
||||
|
@ -395,7 +400,7 @@ class ServiceConfigDialog(Dialog):
|
|||
else:
|
||||
logging.debug("file already existed")
|
||||
|
||||
def delete_filename(self):
|
||||
def delete_filename(self) -> None:
|
||||
cbb = self.filename_combobox
|
||||
filename = cbb.get()
|
||||
if filename in cbb["values"]:
|
||||
|
@ -407,7 +412,7 @@ class ServiceConfigDialog(Dialog):
|
|||
self.modified_files.remove(filename)
|
||||
|
||||
@classmethod
|
||||
def add_command(cls, event: tk.Event):
|
||||
def add_command(cls, event: tk.Event) -> None:
|
||||
frame_contains_button = event.widget.master
|
||||
listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox
|
||||
command_to_add = frame_contains_button.grid_slaves(row=0, column=0)[0].get()
|
||||
|
@ -419,7 +424,7 @@ class ServiceConfigDialog(Dialog):
|
|||
listbox.insert(tk.END, command_to_add)
|
||||
|
||||
@classmethod
|
||||
def update_entry(cls, event: tk.Event):
|
||||
def update_entry(cls, event: tk.Event) -> None:
|
||||
listbox = event.widget
|
||||
current_selection = listbox.curselection()
|
||||
if len(current_selection) > 0:
|
||||
|
@ -431,7 +436,7 @@ class ServiceConfigDialog(Dialog):
|
|||
entry.insert(0, cmd)
|
||||
|
||||
@classmethod
|
||||
def delete_command(cls, event: tk.Event):
|
||||
def delete_command(cls, event: tk.Event) -> None:
|
||||
button = event.widget
|
||||
frame_contains_button = button.master
|
||||
listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox
|
||||
|
@ -441,7 +446,7 @@ class ServiceConfigDialog(Dialog):
|
|||
entry = frame_contains_button.grid_slaves(row=0, column=0)[0]
|
||||
entry.delete(0, tk.END)
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
if (
|
||||
not self.is_custom_command()
|
||||
and not self.is_custom_service_file()
|
||||
|
@ -484,12 +489,12 @@ class ServiceConfigDialog(Dialog):
|
|||
self.app.show_grpc_exception("Save Service Config Error", e)
|
||||
self.destroy()
|
||||
|
||||
def display_service_file_data(self, event: tk.Event):
|
||||
def display_service_file_data(self, event: tk.Event) -> None:
|
||||
filename = self.filename_combobox.get()
|
||||
self.service_file_data.text.delete(1.0, "end")
|
||||
self.service_file_data.text.insert("end", self.temp_service_files[filename])
|
||||
|
||||
def update_temp_service_file_data(self, event: tk.Event):
|
||||
def update_temp_service_file_data(self, event: tk.Event) -> None:
|
||||
filename = self.filename_combobox.get()
|
||||
self.temp_service_files[filename] = self.service_file_data.text.get(1.0, "end")
|
||||
if self.temp_service_files[filename] != self.original_service_files.get(
|
||||
|
@ -499,7 +504,7 @@ class ServiceConfigDialog(Dialog):
|
|||
else:
|
||||
self.modified_files.discard(filename)
|
||||
|
||||
def is_custom_command(self):
|
||||
def is_custom_command(self) -> bool:
|
||||
startup, validate, shutdown = self.get_commands()
|
||||
return (
|
||||
set(self.default_startup) != set(startup)
|
||||
|
@ -507,16 +512,16 @@ class ServiceConfigDialog(Dialog):
|
|||
or set(self.default_shutdown) != set(shutdown)
|
||||
)
|
||||
|
||||
def has_new_files(self):
|
||||
def has_new_files(self) -> bool:
|
||||
return set(self.filenames) != set(self.filename_combobox["values"])
|
||||
|
||||
def is_custom_service_file(self):
|
||||
def is_custom_service_file(self) -> bool:
|
||||
return len(self.modified_files) > 0
|
||||
|
||||
def is_custom_directory(self):
|
||||
def is_custom_directory(self) -> bool:
|
||||
return set(self.default_directories) != set(self.dir_list.listbox.get(0, "end"))
|
||||
|
||||
def click_defaults(self):
|
||||
def click_defaults(self) -> None:
|
||||
"""
|
||||
clears out any custom configuration permanently
|
||||
"""
|
||||
|
@ -557,37 +562,37 @@ class ServiceConfigDialog(Dialog):
|
|||
|
||||
self.current_service_color("")
|
||||
|
||||
def click_copy(self):
|
||||
def click_copy(self) -> None:
|
||||
dialog = CopyServiceConfigDialog(self, self.app, self.node_id)
|
||||
dialog.show()
|
||||
|
||||
@classmethod
|
||||
def append_commands(
|
||||
cls, commands: List[str], listbox: tk.Listbox, to_add: List[str]
|
||||
):
|
||||
) -> None:
|
||||
for cmd in to_add:
|
||||
commands.append(cmd)
|
||||
listbox.insert(tk.END, cmd)
|
||||
|
||||
def get_commands(self):
|
||||
def get_commands(self) -> Tuple[List[str], List[str], List[str]]:
|
||||
startup = self.startup_commands_listbox.get(0, "end")
|
||||
shutdown = self.shutdown_commands_listbox.get(0, "end")
|
||||
validate = self.validate_commands_listbox.get(0, "end")
|
||||
return startup, validate, shutdown
|
||||
|
||||
def find_directory_button(self):
|
||||
def find_directory_button(self) -> None:
|
||||
d = filedialog.askdirectory(initialdir="/")
|
||||
self.directory_entry.delete(0, "end")
|
||||
self.directory_entry.insert("end", d)
|
||||
|
||||
def add_directory(self):
|
||||
def add_directory(self) -> None:
|
||||
d = self.directory_entry.get()
|
||||
if os.path.isdir(d):
|
||||
if d not in self.temp_directories:
|
||||
self.dir_list.listbox.insert("end", d)
|
||||
self.temp_directories.append(d)
|
||||
|
||||
def remove_directory(self):
|
||||
def remove_directory(self) -> None:
|
||||
d = self.directory_entry.get()
|
||||
dirs = self.dir_list.listbox.get(0, "end")
|
||||
if d and d in self.temp_directories:
|
||||
|
@ -599,14 +604,14 @@ class ServiceConfigDialog(Dialog):
|
|||
logging.debug("directory is not in the list")
|
||||
self.directory_entry.delete(0, "end")
|
||||
|
||||
def directory_select(self, event):
|
||||
def directory_select(self, event) -> None:
|
||||
i = self.dir_list.listbox.curselection()
|
||||
if i:
|
||||
d = self.dir_list.listbox.get(i)
|
||||
self.directory_entry.delete(0, "end")
|
||||
self.directory_entry.insert("end", d)
|
||||
|
||||
def current_service_color(self, color=""):
|
||||
def current_service_color(self, color="") -> None:
|
||||
"""
|
||||
change the current service label color
|
||||
"""
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import logging
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc.common_pb2 import ConfigOption
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.themes import PADX, PADY
|
||||
from core.gui.widgets import ConfigFrame
|
||||
|
@ -13,15 +14,15 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class SessionOptionsDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Session Options")
|
||||
self.config_frame = None
|
||||
self.has_error = False
|
||||
self.config = self.get_config()
|
||||
self.config_frame: Optional[ConfigFrame] = None
|
||||
self.has_error: bool = False
|
||||
self.config: Dict[str, ConfigOption] = self.get_config()
|
||||
if not self.has_error:
|
||||
self.draw()
|
||||
|
||||
def get_config(self):
|
||||
def get_config(self) -> Dict[str, ConfigOption]:
|
||||
try:
|
||||
session_id = self.app.core.session_id
|
||||
response = self.app.core.client.get_session_options(session_id)
|
||||
|
@ -31,7 +32,7 @@ class SessionOptionsDialog(Dialog):
|
|||
self.has_error = True
|
||||
self.destroy()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
|
||||
|
@ -48,7 +49,7 @@ class SessionOptionsDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def save(self):
|
||||
def save(self) -> None:
|
||||
config = self.config_frame.parse_config()
|
||||
try:
|
||||
session_id = self.app.core.session_id
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import logging
|
||||
import tkinter as tk
|
||||
from tkinter import messagebox, ttk
|
||||
from typing import TYPE_CHECKING, List
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from core.api.grpc.core_pb2 import SessionSummary
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.images import ImageEnum, Images
|
||||
from core.gui.task import ProgressTask
|
||||
|
@ -18,17 +19,17 @@ if TYPE_CHECKING:
|
|||
class SessionsDialog(Dialog):
|
||||
def __init__(self, app: "Application", is_start_app: bool = False) -> None:
|
||||
super().__init__(app, "Sessions")
|
||||
self.is_start_app = is_start_app
|
||||
self.selected_session = None
|
||||
self.selected_id = None
|
||||
self.tree = None
|
||||
self.sessions = self.get_sessions()
|
||||
self.connect_button = None
|
||||
self.delete_button = None
|
||||
self.is_start_app: bool = is_start_app
|
||||
self.selected_session: Optional[int] = None
|
||||
self.selected_id: Optional[int] = None
|
||||
self.tree: Optional[ttk.Treeview] = None
|
||||
self.sessions: List[SessionSummary] = self.get_sessions()
|
||||
self.connect_button: Optional[ttk.Button] = None
|
||||
self.delete_button: Optional[ttk.Button] = None
|
||||
self.protocol("WM_DELETE_WINDOW", self.on_closing)
|
||||
self.draw()
|
||||
|
||||
def get_sessions(self) -> List[core_pb2.SessionSummary]:
|
||||
def get_sessions(self) -> List[SessionSummary]:
|
||||
try:
|
||||
response = self.app.core.client.get_sessions()
|
||||
logging.info("sessions: %s", response)
|
||||
|
|
|
@ -3,7 +3,7 @@ shape input dialog
|
|||
"""
|
||||
import tkinter as tk
|
||||
from tkinter import font, ttk
|
||||
from typing import TYPE_CHECKING, List, Union
|
||||
from typing import TYPE_CHECKING, List, Optional, Union
|
||||
|
||||
from core.gui.dialogs.colorpicker import ColorPickerDialog
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
|
@ -13,40 +13,41 @@ from core.gui.themes import FRAME_PAD, PADX, PADY
|
|||
|
||||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.graph.shape import Shape
|
||||
|
||||
FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]
|
||||
BORDER_WIDTH = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
FONT_SIZES: List[int] = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]
|
||||
BORDER_WIDTH: List[int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
|
||||
|
||||
class ShapeDialog(Dialog):
|
||||
def __init__(self, app: "Application", shape: "Shape"):
|
||||
def __init__(self, app: "Application", shape: "Shape") -> None:
|
||||
if is_draw_shape(shape.shape_type):
|
||||
title = "Add Shape"
|
||||
else:
|
||||
title = "Add Text"
|
||||
super().__init__(app, title)
|
||||
self.canvas = app.canvas
|
||||
self.fill = None
|
||||
self.border = None
|
||||
self.shape = shape
|
||||
self.canvas: "CanvasGraph" = app.canvas
|
||||
self.fill: Optional[ttk.Label] = None
|
||||
self.border: Optional[ttk.Label] = None
|
||||
self.shape: "Shape" = shape
|
||||
data = shape.shape_data
|
||||
self.shape_text = tk.StringVar(value=data.text)
|
||||
self.font = tk.StringVar(value=data.font)
|
||||
self.font_size = tk.IntVar(value=data.font_size)
|
||||
self.text_color = data.text_color
|
||||
self.shape_text: tk.StringVar = tk.StringVar(value=data.text)
|
||||
self.font: tk.StringVar = tk.StringVar(value=data.font)
|
||||
self.font_size: tk.IntVar = tk.IntVar(value=data.font_size)
|
||||
self.text_color: str = data.text_color
|
||||
fill_color = data.fill_color
|
||||
if not fill_color:
|
||||
fill_color = "#CFCFFF"
|
||||
self.fill_color = fill_color
|
||||
self.border_color = data.border_color
|
||||
self.border_width = tk.IntVar(value=0)
|
||||
self.bold = tk.BooleanVar(value=data.bold)
|
||||
self.italic = tk.BooleanVar(value=data.italic)
|
||||
self.underline = tk.BooleanVar(value=data.underline)
|
||||
self.fill_color: str = fill_color
|
||||
self.border_color: str = data.border_color
|
||||
self.border_width: tk.IntVar = tk.IntVar(value=0)
|
||||
self.bold: tk.BooleanVar = tk.BooleanVar(value=data.bold)
|
||||
self.italic: tk.BooleanVar = tk.BooleanVar(value=data.italic)
|
||||
self.underline: tk.BooleanVar = tk.BooleanVar(value=data.underline)
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.draw_label_options()
|
||||
if is_draw_shape(self.shape.shape_type):
|
||||
|
@ -54,7 +55,7 @@ class ShapeDialog(Dialog):
|
|||
self.draw_spacer()
|
||||
self.draw_buttons()
|
||||
|
||||
def draw_label_options(self):
|
||||
def draw_label_options(self) -> None:
|
||||
label_frame = ttk.LabelFrame(self.top, text="Label", padding=FRAME_PAD)
|
||||
label_frame.grid(sticky="ew")
|
||||
label_frame.columnconfigure(0, weight=1)
|
||||
|
@ -94,7 +95,7 @@ class ShapeDialog(Dialog):
|
|||
button = ttk.Checkbutton(frame, variable=self.underline, text="Underline")
|
||||
button.grid(row=0, column=2, sticky="ew")
|
||||
|
||||
def draw_shape_options(self):
|
||||
def draw_shape_options(self) -> None:
|
||||
label_frame = ttk.LabelFrame(self.top, text="Shape", padding=FRAME_PAD)
|
||||
label_frame.grid(sticky="ew", pady=PADY)
|
||||
label_frame.columnconfigure(0, weight=1)
|
||||
|
@ -129,7 +130,7 @@ class ShapeDialog(Dialog):
|
|||
)
|
||||
combobox.grid(row=0, column=1, sticky="nsew")
|
||||
|
||||
def draw_buttons(self):
|
||||
def draw_buttons(self) -> None:
|
||||
frame = ttk.Frame(self.top)
|
||||
frame.grid(sticky="nsew")
|
||||
frame.columnconfigure(0, weight=1)
|
||||
|
@ -139,28 +140,28 @@ class ShapeDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.cancel)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def choose_text_color(self):
|
||||
def choose_text_color(self) -> None:
|
||||
color_picker = ColorPickerDialog(self, self.app, self.text_color)
|
||||
self.text_color = color_picker.askcolor()
|
||||
|
||||
def choose_fill_color(self):
|
||||
def choose_fill_color(self) -> None:
|
||||
color_picker = ColorPickerDialog(self, self.app, self.fill_color)
|
||||
color = color_picker.askcolor()
|
||||
self.fill_color = color
|
||||
self.fill.config(background=color, text=color)
|
||||
|
||||
def choose_border_color(self):
|
||||
def choose_border_color(self) -> None:
|
||||
color_picker = ColorPickerDialog(self, self.app, self.border_color)
|
||||
color = color_picker.askcolor()
|
||||
self.border_color = color
|
||||
self.border.config(background=color, text=color)
|
||||
|
||||
def cancel(self):
|
||||
def cancel(self) -> None:
|
||||
self.shape.delete()
|
||||
self.canvas.shapes.pop(self.shape.id)
|
||||
self.destroy()
|
||||
|
||||
def click_add(self):
|
||||
def click_add(self) -> None:
|
||||
if is_draw_shape(self.shape.shape_type):
|
||||
self.add_shape()
|
||||
elif is_shape_text(self.shape.shape_type):
|
||||
|
@ -181,7 +182,7 @@ class ShapeDialog(Dialog):
|
|||
text_font.append("underline")
|
||||
return text_font
|
||||
|
||||
def save_text(self):
|
||||
def save_text(self) -> None:
|
||||
"""
|
||||
save info related to text or shape label
|
||||
"""
|
||||
|
@ -194,7 +195,7 @@ class ShapeDialog(Dialog):
|
|||
data.italic = self.italic.get()
|
||||
data.underline = self.underline.get()
|
||||
|
||||
def save_shape(self):
|
||||
def save_shape(self) -> None:
|
||||
"""
|
||||
save info related to shape
|
||||
"""
|
||||
|
@ -203,7 +204,7 @@ class ShapeDialog(Dialog):
|
|||
data.border_color = self.border_color
|
||||
data.border_width = int(self.border_width.get())
|
||||
|
||||
def add_text(self):
|
||||
def add_text(self) -> None:
|
||||
"""
|
||||
add text to canvas
|
||||
"""
|
||||
|
@ -214,7 +215,7 @@ class ShapeDialog(Dialog):
|
|||
)
|
||||
self.save_text()
|
||||
|
||||
def add_shape(self):
|
||||
def add_shape(self) -> None:
|
||||
self.canvas.itemconfig(
|
||||
self.shape.id,
|
||||
fill=self.fill_color,
|
||||
|
|
|
@ -3,10 +3,11 @@ throughput dialog
|
|||
"""
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from core.gui.dialogs.colorpicker import ColorPickerDialog
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
from core.gui.themes import FRAME_PAD, PADX, PADY
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -14,21 +15,23 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
class ThroughputDialog(Dialog):
|
||||
def __init__(self, app: "Application"):
|
||||
def __init__(self, app: "Application") -> None:
|
||||
super().__init__(app, "Throughput Config")
|
||||
self.canvas = app.canvas
|
||||
self.show_throughput = tk.IntVar(value=1)
|
||||
self.exponential_weight = tk.IntVar(value=1)
|
||||
self.transmission = tk.IntVar(value=1)
|
||||
self.reception = tk.IntVar(value=1)
|
||||
self.threshold = tk.DoubleVar(value=self.canvas.throughput_threshold)
|
||||
self.width = tk.IntVar(value=self.canvas.throughput_width)
|
||||
self.color = self.canvas.throughput_color
|
||||
self.color_button = None
|
||||
self.canvas: CanvasGraph = app.canvas
|
||||
self.show_throughput: tk.IntVar = tk.IntVar(value=1)
|
||||
self.exponential_weight: tk.IntVar = tk.IntVar(value=1)
|
||||
self.transmission: tk.IntVar = tk.IntVar(value=1)
|
||||
self.reception: tk.IntVar = tk.IntVar(value=1)
|
||||
self.threshold: tk.DoubleVar = tk.DoubleVar(
|
||||
value=self.canvas.throughput_threshold
|
||||
)
|
||||
self.width: tk.IntVar = tk.IntVar(value=self.canvas.throughput_width)
|
||||
self.color: str = self.canvas.throughput_color
|
||||
self.color_button: Optional[tk.Button] = None
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.draw()
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
button = ttk.Checkbutton(
|
||||
self.top,
|
||||
variable=self.show_throughput,
|
||||
|
@ -97,12 +100,12 @@ class ThroughputDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_color(self):
|
||||
def click_color(self) -> None:
|
||||
color_picker = ColorPickerDialog(self, self.app, self.color)
|
||||
self.color = color_picker.askcolor()
|
||||
self.color_button.config(bg=self.color, text=self.color, bd=0)
|
||||
|
||||
def click_save(self):
|
||||
def click_save(self) -> None:
|
||||
self.canvas.throughput_threshold = self.threshold.get()
|
||||
self.canvas.throughput_width = self.width.get()
|
||||
self.canvas.throughput_color = self.color
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
|
||||
import grpc
|
||||
|
||||
from core.api.grpc.common_pb2 import ConfigOption
|
||||
from core.api.grpc.core_pb2 import Node
|
||||
from core.gui.dialogs.dialog import Dialog
|
||||
from core.gui.themes import PADX, PADY
|
||||
from core.gui.widgets import ConfigFrame
|
||||
|
@ -10,34 +12,36 @@ from core.gui.widgets import ConfigFrame
|
|||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
from core.gui.graph.node import CanvasNode
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
|
||||
RANGE_COLOR = "#009933"
|
||||
RANGE_WIDTH = 3
|
||||
RANGE_COLOR: str = "#009933"
|
||||
RANGE_WIDTH: int = 3
|
||||
|
||||
|
||||
class WlanConfigDialog(Dialog):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode"):
|
||||
def __init__(self, app: "Application", canvas_node: "CanvasNode") -> None:
|
||||
super().__init__(app, f"{canvas_node.core_node.name} WLAN Configuration")
|
||||
self.canvas_node = canvas_node
|
||||
self.node = canvas_node.core_node
|
||||
self.config_frame = None
|
||||
self.range_entry = None
|
||||
self.has_error = False
|
||||
self.canvas = app.canvas
|
||||
self.ranges = {}
|
||||
self.positive_int = self.app.master.register(self.validate_and_update)
|
||||
self.canvas: "CanvasGraph" = app.canvas
|
||||
self.canvas_node: "CanvasNode" = canvas_node
|
||||
self.node: Node = canvas_node.core_node
|
||||
self.config_frame: Optional[ConfigFrame] = None
|
||||
self.range_entry: Optional[ttk.Entry] = None
|
||||
self.has_error: bool = False
|
||||
self.ranges: Dict[int, int] = {}
|
||||
self.positive_int: int = self.app.master.register(self.validate_and_update)
|
||||
try:
|
||||
self.config = self.canvas_node.wlan_config
|
||||
if not self.config:
|
||||
self.config = self.app.core.get_wlan_config(self.node.id)
|
||||
config = self.canvas_node.wlan_config
|
||||
if not config:
|
||||
config = self.app.core.get_wlan_config(self.node.id)
|
||||
self.config: Dict[str, ConfigOption] = config
|
||||
self.init_draw_range()
|
||||
self.draw()
|
||||
except grpc.RpcError as e:
|
||||
self.app.show_grpc_exception("WLAN Config Error", e)
|
||||
self.has_error = True
|
||||
self.has_error: bool = True
|
||||
self.destroy()
|
||||
|
||||
def init_draw_range(self):
|
||||
def init_draw_range(self) -> None:
|
||||
if self.canvas_node.id in self.canvas.wireless_network:
|
||||
for cid in self.canvas.wireless_network[self.canvas_node.id]:
|
||||
x, y = self.canvas.coords(cid)
|
||||
|
@ -46,7 +50,7 @@ class WlanConfigDialog(Dialog):
|
|||
)
|
||||
self.ranges[cid] = range_id
|
||||
|
||||
def draw(self):
|
||||
def draw(self) -> None:
|
||||
self.top.columnconfigure(0, weight=1)
|
||||
self.top.rowconfigure(0, weight=1)
|
||||
self.config_frame = ConfigFrame(self.top, self.app, self.config)
|
||||
|
@ -55,7 +59,7 @@ class WlanConfigDialog(Dialog):
|
|||
self.draw_apply_buttons()
|
||||
self.top.bind("<Destroy>", self.remove_ranges)
|
||||
|
||||
def draw_apply_buttons(self):
|
||||
def draw_apply_buttons(self) -> None:
|
||||
"""
|
||||
create node configuration options
|
||||
"""
|
||||
|
@ -75,7 +79,7 @@ class WlanConfigDialog(Dialog):
|
|||
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||
button.grid(row=0, column=1, sticky="ew")
|
||||
|
||||
def click_apply(self):
|
||||
def click_apply(self) -> None:
|
||||
"""
|
||||
retrieve user's wlan configuration and store the new configuration values
|
||||
"""
|
||||
|
@ -87,7 +91,7 @@ class WlanConfigDialog(Dialog):
|
|||
self.remove_ranges()
|
||||
self.destroy()
|
||||
|
||||
def remove_ranges(self, event=None):
|
||||
def remove_ranges(self, event=None) -> None:
|
||||
for cid in self.canvas.find_withtag("range"):
|
||||
self.canvas.delete(cid)
|
||||
self.ranges.clear()
|
||||
|
|
|
@ -57,7 +57,9 @@ class CanvasNode:
|
|||
self.antennas: List[int] = []
|
||||
self.antenna_images: Dict[int, PhotoImage] = {}
|
||||
# possible configurations
|
||||
self.emane_model_configs: Dict[Tuple[str, Optional[int]], ConfigOption] = {}
|
||||
self.emane_model_configs: Dict[
|
||||
Tuple[str, Optional[int]], Dict[str, ConfigOption]
|
||||
] = {}
|
||||
self.wlan_config: Dict[str, ConfigOption] = {}
|
||||
self.mobility_config: Dict[str, ConfigOption] = {}
|
||||
self.service_configs: Dict[str, NodeServiceData] = {}
|
||||
|
@ -135,7 +137,7 @@ class CanvasNode:
|
|||
new_y = self._get_label_y()
|
||||
self.canvas.move(self.text_id, 0, new_y - prev_y)
|
||||
|
||||
def move(self, x: int, y: int) -> None:
|
||||
def move(self, x: float, y: float) -> None:
|
||||
x, y = self.canvas.get_scaled_coords(x, y)
|
||||
current_x, current_y = self.canvas.coords(self.id)
|
||||
x_offset = x - current_x
|
||||
|
|
|
@ -49,7 +49,7 @@ class Menubar(tk.Menu):
|
|||
self.canvas: CanvasGraph = app.canvas
|
||||
self.recent_menu: Optional[tk.Menu] = None
|
||||
self.edit_menu: Optional[tk.Menu] = None
|
||||
self.observers_menu: Optional[tk.Menu] = None
|
||||
self.observers_menu: Optional[ObserversMenu] = None
|
||||
self.draw()
|
||||
|
||||
def draw(self) -> None:
|
||||
|
|
|
@ -14,7 +14,7 @@ ANTENNA_SIZE: int = 32
|
|||
class NodeDraw:
|
||||
def __init__(self) -> None:
|
||||
self.custom: bool = False
|
||||
self.image: Optional[str] = None
|
||||
self.image: Optional[PhotoImage] = None
|
||||
self.image_enum: Optional[ImageEnum] = None
|
||||
self.image_file: Optional[str] = None
|
||||
self.node_type: NodeType = None
|
||||
|
|
Loading…
Reference in a new issue