more on type hinting, remove unecessary function comments

This commit is contained in:
Huy Pham 2020-01-13 12:03:13 -08:00
parent 7bbd6aa353
commit eb5f2c5648
34 changed files with 169 additions and 326 deletions

View file

@ -204,7 +204,7 @@ class CoreClient:
self.handling_throughputs.cancel() self.handling_throughputs.cancel()
self.handling_throughputs = None self.handling_throughputs = None
def handle_throughputs(self, event): def handle_throughputs(self, event: core_pb2.ThroughputsEvent):
if event.session_id != self.session_id: if event.session_id != self.session_id:
logging.warning( logging.warning(
"ignoring throughput event session(%s) current(%s)", "ignoring throughput event session(%s) current(%s)",
@ -303,7 +303,7 @@ class CoreClient:
def is_runtime(self) -> bool: def is_runtime(self) -> bool:
return self.state == core_pb2.SessionState.RUNTIME return self.state == core_pb2.SessionState.RUNTIME
def parse_metadata(self, config): def parse_metadata(self, config: Dict[str, str]):
# canvas setting # canvas setting
canvas_config = config.get("canvas") canvas_config = config.get("canvas")
logging.info("canvas metadata: %s", canvas_config) logging.info("canvas metadata: %s", canvas_config)
@ -367,8 +367,6 @@ class CoreClient:
def create_new_session(self): def create_new_session(self):
""" """
Create a new session Create a new session
:return: nothing
""" """
try: try:
response = self.client.create_session() response = self.client.create_session()
@ -399,8 +397,6 @@ class CoreClient:
def set_up(self): def set_up(self):
""" """
Query sessions, if there exist any, prompt whether to join one Query sessions, if there exist any, prompt whether to join one
:return: existing sessions
""" """
try: try:
self.client.connect() self.client.connect()
@ -534,9 +530,6 @@ class CoreClient:
def save_xml(self, file_path: str): def save_xml(self, file_path: str):
""" """
Save core session as to an xml file Save core session as to an xml file
:param str file_path: file path that user pick
:return: nothing
""" """
try: try:
if self.state != core_pb2.SessionState.RUNTIME: if self.state != core_pb2.SessionState.RUNTIME:
@ -552,9 +545,6 @@ class CoreClient:
def open_xml(self, file_path: str): def open_xml(self, file_path: str):
""" """
Open core xml Open core xml
:param str file_path: file to open
:return: session id
""" """
try: try:
response = self.client.open_xml(file_path) response = self.client.open_xml(file_path)
@ -596,7 +586,7 @@ class CoreClient:
return response.data return response.data
def set_node_service_file( def set_node_service_file(
self, node_id: int, service_name: str, file_name: str, data: str self, node_id: int, service_name: str, file_name: str, data: bytes
): ):
response = self.client.set_node_service_file( response = self.client.set_node_service_file(
self.session_id, node_id, service_name, file_name, data self.session_id, node_id, service_name, file_name, data
@ -606,8 +596,6 @@ class CoreClient:
def create_nodes_and_links(self): def create_nodes_and_links(self):
""" """
create nodes and links that have not been created yet create nodes and links that have not been created yet
:return: nothing
""" """
node_protos = [x.core_node for x in self.canvas_nodes.values()] node_protos = [x.core_node for x in self.canvas_nodes.values()]
link_protos = [x.link for x in self.links.values()] link_protos = [x.link for x in self.links.values()]
@ -634,8 +622,6 @@ class CoreClient:
def send_data(self): def send_data(self):
""" """
send to daemon all session info, but don't start the session send to daemon all session info, but don't start the session
:return: nothing
""" """
self.create_nodes_and_links() self.create_nodes_and_links()
for config_proto in self.get_wlan_configs_proto(): for config_proto in self.get_wlan_configs_proto():
@ -680,18 +666,13 @@ class CoreClient:
def close(self): def close(self):
""" """
Clean ups when done using grpc Clean ups when done using grpc
:return: nothing
""" """
logging.debug("close grpc") logging.debug("close grpc")
self.client.close() self.client.close()
def next_node_id(self): def next_node_id(self) -> int:
""" """
Get the next usable node id. Get the next usable node id.
:return: the next id to be used
:rtype: int
""" """
i = 1 i = 1
while True: while True:
@ -743,9 +724,6 @@ class CoreClient:
""" """
remove the nodes selected by the user and anything related to that node remove the nodes selected by the user and anything related to that node
such as link, configurations, interfaces such as link, configurations, interfaces
:param list canvas_nodes: list of nodes to delete
:return: nothing
""" """
edges = set() edges = set()
for canvas_node in canvas_nodes: for canvas_node in canvas_nodes:
@ -767,9 +745,6 @@ class CoreClient:
if edge in edges: if edge in edges:
continue continue
edges.add(edge) edges.add(edge)
#
# if edge.token not in self.links:
# logging.error("unknown edge: %s", edge.token)
self.links.pop(edge.token, None) self.links.pop(edge.token, None)
def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface: def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface:
@ -795,12 +770,6 @@ class CoreClient:
""" """
Create core link for a pair of canvas nodes, with token referencing Create core link for a pair of canvas nodes, with token referencing
the canvas edge. the canvas edge.
:param edge: edge for link
:param canvas_src_node: canvas node one
:param canvas_dst_node: canvas node two
:return: nothing
""" """
src_node = canvas_src_node.core_node src_node = canvas_src_node.core_node
dst_node = canvas_dst_node.core_node dst_node = canvas_dst_node.core_node

View file

@ -110,7 +110,7 @@ class AlertsDialog(Dialog):
dialog = DaemonLog(self, self.app) dialog = DaemonLog(self, self.app)
dialog.show() dialog.show()
def click_select(self, event): def click_select(self, event: tk.Event):
current = self.tree.selection()[0] current = self.tree.selection()[0]
alarm = self.alarm_map[current] alarm = self.alarm_map[current]
self.codetext.text.config(state=tk.NORMAL) self.codetext.text.config(state=tk.NORMAL)

View file

@ -14,8 +14,6 @@ class SizeAndScaleDialog(Dialog):
def __init__(self, master, app): def __init__(self, master, app):
""" """
create an instance for size and scale object create an instance for size and scale object
:param app: main application
""" """
super().__init__(master, app, "Canvas Size and Scale", modal=True) super().__init__(master, app, "Canvas Size and Scale", modal=True)
self.canvas = self.app.canvas self.canvas = self.app.canvas

View file

@ -140,8 +140,6 @@ class CanvasWallpaperDialog(Dialog):
def click_clear(self): def click_clear(self):
""" """
delete like shown in image link entry if there is any delete like shown in image link entry if there is any
:return: nothing
""" """
# delete entry # delete entry
self.filename.set("") self.filename.set("")

View file

@ -31,7 +31,7 @@ class ColorPickerDialog(Dialog):
self.draw() self.draw()
self.set_bindings() self.set_bindings()
def askcolor(self): def askcolor(self) -> str:
self.show() self.show()
return self.color return self.color
@ -175,12 +175,9 @@ class ColorPickerDialog(Dialog):
self.color = self.hex.get() self.color = self.hex.get()
self.destroy() self.destroy()
def get_hex(self): def get_hex(self) -> str:
""" """
convert current RGB values into hex color convert current RGB values into hex color
:rtype: str
:return: hex color
""" """
red = self.red_entry.get() red = self.red_entry.get()
blue = self.blue_entry.get() blue = self.blue_entry.get()
@ -210,35 +207,31 @@ class ColorPickerDialog(Dialog):
self.set_entry(red, green, blue) self.set_entry(red, green, blue)
self.set_scale(red, green, blue) self.set_scale(red, green, blue)
self.display.config(background=hex_code) self.display.config(background=hex_code)
self.set_label(red, green, blue) self.set_label(str(red), str(green), str(blue))
def scale_callback(self, var, color_var): def scale_callback(self, var: tk.IntVar, color_var: tk.IntVar):
color_var.set(var.get()) color_var.set(var.get())
self.focus = "rgb" self.focus = "rgb"
self.update_color() self.update_color()
def set_scale(self, red, green, blue): def set_scale(self, red: int, green: int, blue: int):
self.red_scale.set(red) self.red_scale.set(red)
self.green_scale.set(green) self.green_scale.set(green)
self.blue_scale.set(blue) self.blue_scale.set(blue)
def set_entry(self, red, green, blue): def set_entry(self, red: int, green: int, blue: int):
self.red.set(red) self.red.set(red)
self.green.set(green) self.green.set(green)
self.blue.set(blue) self.blue.set(blue)
def set_label(self, red, green, blue): def set_label(self, red: str, green: str, blue: str):
self.red_label.configure(background="#%02x%02x%02x" % (int(red), 0, 0)) 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.green_label.configure(background="#%02x%02x%02x" % (0, int(green), 0))
self.blue_label.configure(background="#%02x%02x%02x" % (0, 0, int(blue))) self.blue_label.configure(background="#%02x%02x%02x" % (0, 0, int(blue)))
def get_rgb(self, hex_code): def get_rgb(self, hex_code: str) -> [int, int, int]:
""" """
convert a valid hex code to RGB values convert a valid hex code to RGB values
:param string hex_code: color in hex
:rtype: tuple(int, int, int)
:return: the RGB values
""" """
if len(hex_code) == 4: if len(hex_code) == 4:
red = hex_code[1] red = hex_code[1]

View file

@ -5,6 +5,7 @@ copy service config dialog
import logging import logging
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import Tuple
from core.gui.dialogs.dialog import Dialog from core.gui.dialogs.dialog import Dialog
from core.gui.themes import FRAME_PAD, PADX from core.gui.themes import FRAME_PAD, PADX
@ -147,7 +148,7 @@ class CopyServiceConfigDialog(Dialog):
dialog = ViewConfigDialog(self, self.app, self.node_id, data) dialog = ViewConfigDialog(self, self.app, self.node_id, data)
dialog.show() dialog.show()
def get_node_service(self, selected): def get_node_service(self, selected: Tuple[str]) -> [int, str]:
service_tree_id = self.tree.parent(selected[0]) service_tree_id = self.tree.parent(selected[0])
service_name = self.tree.item(service_tree_id)["text"] service_name = self.tree.item(service_tree_id)["text"]
node_tree_id = self.tree.parent(service_tree_id) node_tree_id = self.tree.parent(service_tree_id)

View file

@ -71,7 +71,7 @@ class ServicesSelectDialog(Dialog):
# trigger group change # trigger group change
self.groups.listbox.event_generate("<<ListboxSelect>>") self.groups.listbox.event_generate("<<ListboxSelect>>")
def handle_group_change(self, event): def handle_group_change(self, event: tk.Event):
selection = self.groups.listbox.curselection() selection = self.groups.listbox.curselection()
if selection: if selection:
index = selection[0] index = selection[0]
@ -81,7 +81,7 @@ class ServicesSelectDialog(Dialog):
checked = name in self.current_services checked = name in self.current_services
self.services.add(name, checked) self.services.add(name, checked)
def service_clicked(self, name, var): def service_clicked(self, name: str, var: tk.BooleanVar):
if var.get() and name not in self.current_services: if var.get() and name not in self.current_services:
self.current_services.add(name) self.current_services.add(name)
elif not var.get() and name in self.current_services: elif not var.get() and name in self.current_services:

View file

@ -1,5 +1,6 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import Optional
from core.gui.images import ImageEnum, Images from core.gui.images import ImageEnum, Images
from core.gui.themes import DIALOG_PAD from core.gui.themes import DIALOG_PAD
@ -30,7 +31,7 @@ class Dialog(tk.Toplevel):
self.grab_set() self.grab_set()
self.wait_window() self.wait_window()
def draw_spacer(self, row=None): def draw_spacer(self, row: Optional[int] = None):
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.grid(row=row, sticky="nsew") frame.grid(row=row, sticky="nsew")
frame.rowconfigure(0, weight=1) frame.rowconfigure(0, weight=1)

View file

@ -116,8 +116,6 @@ class EmaneConfigDialog(Dialog):
def draw_emane_configuration(self): def draw_emane_configuration(self):
""" """
draw the main frame for emane configuration draw the main frame for emane configuration
:return: nothing
""" """
label = ttk.Label( label = ttk.Label(
self.top, self.top,
@ -143,8 +141,6 @@ class EmaneConfigDialog(Dialog):
def draw_emane_models(self): def draw_emane_models(self):
""" """
create a combobox that has all the known emane models create a combobox that has all the known emane models
:return: nothing
""" """
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.grid(sticky="ew", pady=PADY) frame.grid(sticky="ew", pady=PADY)
@ -210,8 +206,6 @@ class EmaneConfigDialog(Dialog):
def click_model_config(self): def click_model_config(self):
""" """
draw emane model configuration draw emane model configuration
:return: nothing
""" """
model_name = self.emane_model.get() model_name = self.emane_model.get()
logging.info("configuring emane model: %s", model_name) logging.info("configuring emane model: %s", model_name)
@ -220,12 +214,9 @@ class EmaneConfigDialog(Dialog):
) )
dialog.show() dialog.show()
def emane_model_change(self, event): def emane_model_change(self, event: tk.Event):
""" """
update emane model options button update emane model options button
:param event:
:return: nothing
""" """
model_name = self.emane_model.get() model_name = self.emane_model.get()
self.emane_model_button.config(text=f"{model_name} options") self.emane_model_button.config(text=f"{model_name} options")

View file

@ -62,11 +62,11 @@ class HookDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=lambda: self.destroy()) button = ttk.Button(frame, text="Cancel", command=lambda: self.destroy())
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
def state_change(self, event): def state_change(self, event: tk.Event):
state_name = self.state.get() state_name = self.state.get()
self.name.set(f"{state_name.lower()}_hook.sh") self.name.set(f"{state_name.lower()}_hook.sh")
def set(self, hook): def set(self, hook: core_pb2.Hook):
self.hook = hook self.hook = hook
self.name.set(hook.file) self.name.set(hook.file)
self.codetext.text.delete(1.0, tk.END) self.codetext.text.delete(1.0, tk.END)
@ -140,7 +140,7 @@ class HooksDialog(Dialog):
self.edit_button.config(state=tk.DISABLED) self.edit_button.config(state=tk.DISABLED)
self.delete_button.config(state=tk.DISABLED) self.delete_button.config(state=tk.DISABLED)
def select(self, event): def select(self, event: tk.Event):
if self.listbox.curselection(): if self.listbox.curselection():
index = self.listbox.curselection()[0] index = self.listbox.curselection()[0]
self.selected = self.listbox.get(index) self.selected = self.listbox.get(index)

View file

@ -4,6 +4,7 @@ link configuration
import logging import logging
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import Union
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from core.gui.dialogs.colorpicker import ColorPickerDialog from core.gui.dialogs.colorpicker import ColorPickerDialog
@ -11,7 +12,7 @@ from core.gui.dialogs.dialog import Dialog
from core.gui.themes import PADX, PADY from core.gui.themes import PADX, PADY
def get_int(var): def get_int(var: tk.StringVar) -> Union[int, None]:
value = var.get() value = var.get()
if value != "": if value != "":
return int(value) return int(value)
@ -19,7 +20,7 @@ def get_int(var):
return None return None
def get_float(var): def get_float(var: tk.StringVar) -> Union[int, None]:
value = var.get() value = var.get()
if value != "": if value != "":
return float(value) return float(value)
@ -103,7 +104,7 @@ class LinkConfigurationDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=self.destroy) button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
def get_frame(self): def get_frame(self) -> ttk.Frame:
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.columnconfigure(1, weight=1) frame.columnconfigure(1, weight=1)
if self.is_symmetric: if self.is_symmetric:
@ -339,8 +340,6 @@ class LinkConfigurationDialog(Dialog):
def load_link_config(self): def load_link_config(self):
""" """
populate link config to the table populate link config to the table
:return: nothing
""" """
width = self.app.canvas.itemcget(self.edge.id, "width") width = self.app.canvas.itemcget(self.edge.id, "width")
self.width.set(width) self.width.set(width)

View file

@ -53,13 +53,13 @@ class MarkerDialog(Dialog):
for i in canvas.find_withtag("marker"): for i in canvas.find_withtag("marker"):
canvas.delete(i) canvas.delete(i)
def change_color(self, event): def change_color(self, event: tk.Event):
color_picker = ColorPickerDialog(self, self.app, self.color) color_picker = ColorPickerDialog(self, self.app, self.color)
color = color_picker.askcolor() color = color_picker.askcolor()
event.widget.configure(background=color) event.widget.configure(background=color)
self.color = color self.color = color
def change_thickness(self, event): def change_thickness(self, event: tk.Event):
self.radius = self.marker_thickness.get() self.radius = self.marker_thickness.get()
def show(self): def show(self):

View file

@ -13,7 +13,7 @@ from core.gui.themes import FRAME_PAD, PADX, PADY
from core.gui.widgets import ListboxScroll, image_chooser from core.gui.widgets import ListboxScroll, image_chooser
def mac_auto(is_auto, entry): def mac_auto(is_auto, entry: ttk.Entry):
logging.info("mac auto clicked") logging.info("mac auto clicked")
if is_auto.get(): if is_auto.get():
logging.info("disabling mac") logging.info("disabling mac")
@ -217,7 +217,7 @@ class NodeConfigDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=self.destroy) button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
def click_emane_config(self, emane_model, interface_id): def click_emane_config(self, emane_model: str, interface_id: int):
dialog = EmaneModelDialog(self, self.app, self.node, emane_model, interface_id) dialog = EmaneModelDialog(self, self.app, self.node, emane_model, interface_id)
dialog.show() dialog.show()
@ -248,7 +248,7 @@ class NodeConfigDialog(Dialog):
self.canvas_node.redraw() self.canvas_node.redraw()
self.destroy() self.destroy()
def interface_select(self, event): def interface_select(self, event: tk.Event):
listbox = event.widget listbox = event.widget
cur = listbox.curselection() cur = listbox.curselection()
if cur: if cur:

View file

@ -87,7 +87,7 @@ class NodeServiceDialog(Dialog):
# trigger group change # trigger group change
self.groups.listbox.event_generate("<<ListboxSelect>>") self.groups.listbox.event_generate("<<ListboxSelect>>")
def handle_group_change(self, event=None): def handle_group_change(self, event: tk.Event = None):
selection = self.groups.listbox.curselection() selection = self.groups.listbox.curselection()
if selection: if selection:
index = selection[0] index = selection[0]
@ -97,7 +97,7 @@ class NodeServiceDialog(Dialog):
checked = name in self.current_services checked = name in self.current_services
self.services.add(name, checked) self.services.add(name, checked)
def service_clicked(self, name, var): def service_clicked(self, name: str, var: tk.IntVar):
if var.get() and name not in self.current_services: if var.get() and name not in self.current_services:
self.current_services.add(name) self.current_services.add(name)
elif not var.get() and name in self.current_services: elif not var.get() and name in self.current_services:
@ -150,7 +150,7 @@ class NodeServiceDialog(Dialog):
checkbutton.invoke() checkbutton.invoke()
return return
def is_custom_service(self, service): def is_custom_service(self, service: str) -> bool:
service_configs = self.app.core.service_configs service_configs = self.app.core.service_configs
file_configs = self.app.core.file_configs file_configs = self.app.core.file_configs
if self.node_id in service_configs and service in service_configs[self.node_id]: if self.node_id in service_configs and service in service_configs[self.node_id]:

View file

@ -126,7 +126,7 @@ class ObserverDialog(Dialog):
self.save_button.config(state=tk.DISABLED) self.save_button.config(state=tk.DISABLED)
self.delete_button.config(state=tk.DISABLED) self.delete_button.config(state=tk.DISABLED)
def handle_observer_change(self, event): def handle_observer_change(self, event: tk.Event):
selection = self.observers.curselection() selection = self.observers.curselection()
if selection: if selection:
self.selected_index = selection[0] self.selected_index = selection[0]

View file

@ -72,7 +72,7 @@ class PreferencesDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=self.destroy) button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=1, sticky="ew") button.grid(row=0, column=1, sticky="ew")
def theme_change(self, event): def theme_change(self, event: tk.Event):
theme = self.theme.get() theme = self.theme.get()
logging.info("changing theme: %s", theme) logging.info("changing theme: %s", theme)
self.app.style.theme_use(theme) self.app.style.theme_use(theme)

View file

@ -155,7 +155,7 @@ class ServersDialog(Dialog):
self.save_button.config(state=tk.DISABLED) self.save_button.config(state=tk.DISABLED)
self.delete_button.config(state=tk.DISABLED) self.delete_button.config(state=tk.DISABLED)
def handle_server_change(self, event): def handle_server_change(self, event: tk.Event):
selection = self.servers.curselection() selection = self.servers.curselection()
if selection: if selection:
self.selected_index = selection[0] self.selected_index = selection[0]

View file

@ -1,6 +1,7 @@
"Service configuration dialog" "Service configuration dialog"
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import List
import grpc import grpc
@ -345,7 +346,7 @@ class ServiceConfigDialog(Dialog):
button = ttk.Button(frame, text="Cancel", command=self.destroy) button = ttk.Button(frame, text="Cancel", command=self.destroy)
button.grid(row=0, column=3, sticky="ew") button.grid(row=0, column=3, sticky="ew")
def add_filename(self, event): def add_filename(self, event: tk.Event):
# not worry about it for now # not worry about it for now
return return
frame_contains_button = event.widget.master frame_contains_button = event.widget.master
@ -354,7 +355,7 @@ class ServiceConfigDialog(Dialog):
if filename not in combobox["values"]: if filename not in combobox["values"]:
combobox["values"] += (filename,) combobox["values"] += (filename,)
def delete_filename(self, event): def delete_filename(self, event: tk.Event):
# not worry about it for now # not worry about it for now
return return
frame_comntains_button = event.widget.master frame_comntains_button = event.widget.master
@ -364,7 +365,7 @@ class ServiceConfigDialog(Dialog):
combobox["values"] = tuple([x for x in combobox["values"] if x != filename]) combobox["values"] = tuple([x for x in combobox["values"] if x != filename])
combobox.set("") combobox.set("")
def add_command(self, event): def add_command(self, event: tk.Event):
frame_contains_button = event.widget.master frame_contains_button = event.widget.master
listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox 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() command_to_add = frame_contains_button.grid_slaves(row=0, column=0)[0].get()
@ -375,7 +376,7 @@ class ServiceConfigDialog(Dialog):
return return
listbox.insert(tk.END, command_to_add) listbox.insert(tk.END, command_to_add)
def update_entry(self, event): def update_entry(self, event: tk.Event):
listbox = event.widget listbox = event.widget
current_selection = listbox.curselection() current_selection = listbox.curselection()
if len(current_selection) > 0: if len(current_selection) > 0:
@ -386,7 +387,7 @@ class ServiceConfigDialog(Dialog):
entry.delete(0, "end") entry.delete(0, "end")
entry.insert(0, cmd) entry.insert(0, cmd)
def delete_command(self, event): def delete_command(self, event: tk.Event):
button = event.widget button = event.widget
frame_contains_button = button.master frame_contains_button = button.master
listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox
@ -439,13 +440,13 @@ class ServiceConfigDialog(Dialog):
show_grpc_error(e) show_grpc_error(e)
self.destroy() self.destroy()
def display_service_file_data(self, event): def display_service_file_data(self, event: tk.Event):
combobox = event.widget combobox = event.widget
filename = combobox.get() filename = combobox.get()
self.service_file_data.text.delete(1.0, "end") self.service_file_data.text.delete(1.0, "end")
self.service_file_data.text.insert("end", self.temp_service_files[filename]) self.service_file_data.text.insert("end", self.temp_service_files[filename])
def update_temp_service_file_data(self, event): def update_temp_service_file_data(self, event: tk.Event):
scrolledtext = event.widget scrolledtext = event.widget
filename = self.filename_combobox.get() filename = self.filename_combobox.get()
self.temp_service_files[filename] = scrolledtext.get(1.0, "end") self.temp_service_files[filename] = scrolledtext.get(1.0, "end")
@ -490,7 +491,9 @@ class ServiceConfigDialog(Dialog):
dialog = CopyServiceConfigDialog(self, self.app, self.node_id) dialog = CopyServiceConfigDialog(self, self.app, self.node_id)
dialog.show() dialog.show()
def append_commands(self, commands, listbox, to_add): def append_commands(
self, commands: List[str], listbox: tk.Listbox, to_add: List[str]
):
for cmd in to_add: for cmd in to_add:
commands.append(cmd) commands.append(cmd)
listbox.insert(tk.END, cmd) listbox.insert(tk.END, cmd)

View file

@ -1,6 +1,7 @@
import logging import logging
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import Iterable
import grpc import grpc
@ -21,7 +22,7 @@ class SessionsDialog(Dialog):
self.sessions = self.get_sessions() self.sessions = self.get_sessions()
self.draw() self.draw()
def get_sessions(self): def get_sessions(self) -> Iterable[core_pb2.SessionSummary]:
try: try:
response = self.app.core.client.get_sessions() response = self.app.core.client.get_sessions()
logging.info("sessions: %s", response) logging.info("sessions: %s", response)
@ -40,7 +41,6 @@ class SessionsDialog(Dialog):
def draw_description(self): def draw_description(self):
""" """
write a short description write a short description
:return: nothing
""" """
label = ttk.Label( label = ttk.Label(
self.top, self.top,
@ -129,7 +129,7 @@ class SessionsDialog(Dialog):
self.app.core.create_new_session() self.app.core.create_new_session()
self.destroy() self.destroy()
def click_select(self, event): def click_select(self, event: tk.Event):
item = self.tree.selection() item = self.tree.selection()
session_id = int(self.tree.item(item, "text")) session_id = int(self.tree.item(item, "text"))
self.selected = True self.selected = True
@ -138,8 +138,6 @@ class SessionsDialog(Dialog):
def click_connect(self): def click_connect(self):
""" """
if no session is selected yet, create a new one else join that session if no session is selected yet, create a new one else join that session
:return: nothing
""" """
if self.selected and self.selected_id is not None: if self.selected and self.selected_id is not None:
self.join_session(self.selected_id) self.join_session(self.selected_id)
@ -152,8 +150,6 @@ class SessionsDialog(Dialog):
""" """
if no session is currently selected create a new session else shut the selected if no session is currently selected create a new session else shut the selected
session down. session down.
:return: nothing
""" """
if self.selected and self.selected_id is not None: if self.selected and self.selected_id is not None:
self.shutdown_session(self.selected_id) self.shutdown_session(self.selected_id)
@ -162,18 +158,18 @@ class SessionsDialog(Dialog):
else: else:
logging.error("querysessiondrawing.py invalid state") logging.error("querysessiondrawing.py invalid state")
def join_session(self, session_id): def join_session(self, session_id: int):
self.app.statusbar.progress_bar.start(5) self.app.statusbar.progress_bar.start(5)
task = BackgroundTask(self.app, self.app.core.join_session, args=(session_id,)) task = BackgroundTask(self.app, self.app.core.join_session, args=(session_id,))
task.start() task.start()
self.destroy() self.destroy()
def on_selected(self, event): def on_selected(self, event: tk.Event):
item = self.tree.selection() item = self.tree.selection()
sid = int(self.tree.item(item, "text")) sid = int(self.tree.item(item, "text"))
self.join_session(sid) self.join_session(sid)
def shutdown_session(self, sid): def shutdown_session(self, sid: int):
self.app.core.stop_session(sid) self.app.core.stop_session(sid)
self.click_new() self.click_new()
self.destroy() self.destroy()

View file

@ -38,8 +38,6 @@ class WlanConfigDialog(Dialog):
def draw_apply_buttons(self): def draw_apply_buttons(self):
""" """
create node configuration options create node configuration options
:return: nothing
""" """
frame = ttk.Frame(self.top) frame = ttk.Frame(self.top)
frame.grid(sticky="ew") frame.grid(sticky="ew")
@ -55,8 +53,6 @@ class WlanConfigDialog(Dialog):
def click_apply(self): def click_apply(self):
""" """
retrieve user's wlan configuration and store the new configuration values retrieve user's wlan configuration and store the new configuration values
:return: nothing
""" """
config = self.config_frame.parse_config() config = self.config_frame.parse_config()
self.app.core.wlan_configs[self.node.id] = self.config self.app.core.wlan_configs[self.node.id] = self.config

View file

@ -14,7 +14,14 @@ EDGE_COLOR = "#ff0000"
class CanvasWirelessEdge: class CanvasWirelessEdge:
def __init__(self, token: Tuple[int, int], position, src: int, dst: int, canvas): def __init__(
self,
token: Tuple[int, int],
position: Tuple[int, int, int, int],
src: int,
dst: int,
canvas,
):
self.token = token self.token = token
self.src = src self.src = src
self.dst = dst self.dst = dst
@ -35,11 +42,6 @@ class CanvasEdge:
def __init__(self, x1: int, y1: int, x2: int, y2: int, src: int, canvas): def __init__(self, x1: int, y1: int, x2: int, y2: int, src: int, canvas):
""" """
Create an instance of canvas edge object Create an instance of canvas edge object
:param int x1: source x-coord
:param int y1: source y-coord
:param int x2: destination x-coord
:param int y2: destination y-coord
:param int src: source id
:param coretk.graph.graph.GraphCanvas canvas: canvas object :param coretk.graph.graph.GraphCanvas canvas: canvas object
""" """
self.src = src self.src = src
@ -67,7 +69,7 @@ class CanvasEdge:
self.link = link self.link = link
self.draw_labels() self.draw_labels()
def get_coordinates(self): def get_coordinates(self) -> [int, int, int, int]:
x1, y1, x2, y2 = self.canvas.coords(self.id) x1, y1, x2, y2 = self.canvas.coords(self.id)
v1 = x2 - x1 v1 = x2 - x1
v2 = y2 - y1 v2 = y2 - y1
@ -79,7 +81,7 @@ class CanvasEdge:
y2 = y2 - uy y2 = y2 - uy
return x1, y1, x2, y2 return x1, y1, x2, y2
def get_midpoint(self): def get_midpoint(self) -> [float, float]:
x1, y1, x2, y2 = self.canvas.coords(self.id) x1, y1, x2, y2 = self.canvas.coords(self.id)
x = (x1 + x2) / 2 x = (x1 + x2) / 2
y = (y1 + y2) / 2 y = (y1 + y2) / 2
@ -119,8 +121,6 @@ class CanvasEdge:
def update_labels(self): def update_labels(self):
""" """
Move edge labels based on current position. Move edge labels based on current position.
:return: nothing
""" """
x1, y1, x2, y2 = self.get_coordinates() x1, y1, x2, y2 = self.get_coordinates()
self.canvas.coords(self.text_src, x1, y1) self.canvas.coords(self.text_src, x1, y1)
@ -158,7 +158,7 @@ class CanvasEdge:
self.canvas.tag_raise(self.src) self.canvas.tag_raise(self.src)
self.canvas.tag_raise(self.dst) self.canvas.tag_raise(self.dst)
def is_wireless(self): def is_wireless(self) -> [bool, bool]:
src_node = self.canvas.nodes[self.src] src_node = self.canvas.nodes[self.src]
dst_node = self.canvas.nodes[self.dst] dst_node = self.canvas.nodes[self.dst]
src_node_type = src_node.core_node.type src_node_type = src_node.core_node.type
@ -184,7 +184,6 @@ class CanvasEdge:
dst_node.add_antenna() dst_node.add_antenna()
elif not is_src_wireless and is_dst_wireless: elif not is_src_wireless and is_dst_wireless:
src_node.add_antenna() src_node.add_antenna()
# TODO: remove this? dont allow linking wireless nodes?
else: else:
src_node.add_antenna() src_node.add_antenna()

View file

@ -1,5 +1,6 @@
import logging import logging
import tkinter as tk import tkinter as tk
from typing import List, Optional
from PIL import Image, ImageTk from PIL import Image, ImageTk
@ -84,13 +85,11 @@ class CanvasGraph(tk.Canvas):
) )
self.configure(scrollregion=self.bbox(tk.ALL)) self.configure(scrollregion=self.bbox(tk.ALL))
def reset_and_redraw(self, session): def reset_and_redraw(self, session: core_pb2.Session):
""" """
Reset the private variables CanvasGraph object, redraw nodes given the new grpc Reset the private variables CanvasGraph object, redraw nodes given the new grpc
client. client.
:param core.api.grpc.core_pb2.Session session: session to draw :param core.api.grpc.core_pb2.Session session: session to draw
:return: nothing
""" """
# hide context # hide context
self.hide_context() self.hide_context()
@ -114,8 +113,6 @@ class CanvasGraph(tk.Canvas):
def setup_bindings(self): def setup_bindings(self):
""" """
Bind any mouse events or hot keys to the matching action Bind any mouse events or hot keys to the matching action
:return: nothing
""" """
self.bind("<ButtonPress-1>", self.click_press) self.bind("<ButtonPress-1>", self.click_press)
self.bind("<ButtonRelease-1>", self.click_release) self.bind("<ButtonRelease-1>", self.click_release)
@ -135,28 +132,28 @@ class CanvasGraph(tk.Canvas):
self.context.unpost() self.context.unpost()
self.context = None self.context = None
def get_actual_coords(self, x, y): def get_actual_coords(self, x: float, y: float) -> [float, float]:
actual_x = (x - self.offset[0]) / self.ratio actual_x = (x - self.offset[0]) / self.ratio
actual_y = (y - self.offset[1]) / self.ratio actual_y = (y - self.offset[1]) / self.ratio
return actual_x, actual_y return actual_x, actual_y
def get_scaled_coords(self, x, y): def get_scaled_coords(self, x: float, y: float) -> [float, float]:
scaled_x = (x * self.ratio) + self.offset[0] scaled_x = (x * self.ratio) + self.offset[0]
scaled_y = (y * self.ratio) + self.offset[1] scaled_y = (y * self.ratio) + self.offset[1]
return scaled_x, scaled_y return scaled_x, scaled_y
def inside_canvas(self, x, y): def inside_canvas(self, x: float, y: float) -> [bool, bool]:
x1, y1, x2, y2 = self.bbox(self.grid) x1, y1, x2, y2 = self.bbox(self.grid)
valid_x = x1 <= x <= x2 valid_x = x1 <= x <= x2
valid_y = y1 <= y <= y2 valid_y = y1 <= y <= y2
return valid_x and valid_y return valid_x and valid_y
def valid_position(self, x1, y1, x2, y2): def valid_position(self, x1: int, y1: int, x2: int, y2: int) -> [bool, bool]:
valid_topleft = self.inside_canvas(x1, y1) valid_topleft = self.inside_canvas(x1, y1)
valid_bottomright = self.inside_canvas(x2, y2) valid_bottomright = self.inside_canvas(x2, y2)
return valid_topleft and valid_bottomright return valid_topleft and valid_bottomright
def set_throughputs(self, throughputs_event): def set_throughputs(self, throughputs_event: core_pb2.ThroughputsEvent):
for interface_throughput in throughputs_event.interface_throughputs: for interface_throughput in throughputs_event.interface_throughputs:
node_id = interface_throughput.node_id node_id = interface_throughput.node_id
interface_id = interface_throughput.interface_id interface_id = interface_throughput.interface_id
@ -174,8 +171,6 @@ class CanvasGraph(tk.Canvas):
def draw_grid(self): def draw_grid(self):
""" """
Create grid. Create grid.
:return: nothing
""" """
width, height = self.width_and_height() width, height = self.width_and_height()
width = int(width) width = int(width)
@ -187,13 +182,12 @@ class CanvasGraph(tk.Canvas):
self.tag_lower(tags.GRIDLINE) self.tag_lower(tags.GRIDLINE)
self.tag_lower(self.grid) self.tag_lower(self.grid)
def add_wireless_edge(self, src, dst): def add_wireless_edge(self, src: CanvasNode, dst: CanvasNode):
""" """
add a wireless edge between 2 canvas nodes add a wireless edge between 2 canvas nodes
:param CanvasNode src: source node :param CanvasNode src: source node
:param CanvasNode dst: destination node :param CanvasNode dst: destination node
:return: nothing
""" """
token = tuple(sorted((src.id, dst.id))) token = tuple(sorted((src.id, dst.id)))
x1, y1 = self.coords(src.id) x1, y1 = self.coords(src.id)
@ -206,18 +200,16 @@ class CanvasGraph(tk.Canvas):
self.tag_raise(src.id) self.tag_raise(src.id)
self.tag_raise(dst.id) self.tag_raise(dst.id)
def delete_wireless_edge(self, src, dst): def delete_wireless_edge(self, src: CanvasNode, dst: CanvasNode):
token = tuple(sorted((src.id, dst.id))) token = tuple(sorted((src.id, dst.id)))
edge = self.wireless_edges.pop(token) edge = self.wireless_edges.pop(token)
edge.delete() edge.delete()
src.wireless_edges.remove(edge) src.wireless_edges.remove(edge)
dst.wireless_edges.remove(edge) dst.wireless_edges.remove(edge)
def draw_session(self, session): def draw_session(self, session: core_pb2.Session):
""" """
Draw existing session. Draw existing session.
:return: nothing
""" """
# draw existing nodes # draw existing nodes
for core_node in session.nodes: for core_node in session.nodes:
@ -296,25 +288,17 @@ class CanvasGraph(tk.Canvas):
for edge in self.edges.values(): for edge in self.edges.values():
edge.reset() edge.reset()
def canvas_xy(self, event): def canvas_xy(self, event: tk.Event) -> [float, float]:
""" """
Convert window coordinate to canvas coordinate Convert window coordinate to canvas coordinate
:param event:
:rtype: (int, int)
:return: x, y canvas coordinate
""" """
x = self.canvasx(event.x) x = self.canvasx(event.x)
y = self.canvasy(event.y) y = self.canvasy(event.y)
return x, y return x, y
def get_selected(self, event): def get_selected(self, event: tk.Event) -> int:
""" """
Retrieve the item id that is on the mouse position Retrieve the item id that is on the mouse position
:param event: mouse event
:rtype: int
:return: the item that the mouse point to
""" """
x, y = self.canvas_xy(event) x, y = self.canvas_xy(event)
overlapping = self.find_overlapping(x, y, x, y) overlapping = self.find_overlapping(x, y, x, y)
@ -332,7 +316,7 @@ class CanvasGraph(tk.Canvas):
return selected return selected
def click_release(self, event): def click_release(self, event: tk.Event):
""" """
Draw a node or finish drawing an edge according to the current graph mode Draw a node or finish drawing an edge according to the current graph mode
@ -380,7 +364,7 @@ class CanvasGraph(tk.Canvas):
self.mode = GraphMode.NODE self.mode = GraphMode.NODE
self.selected = None self.selected = None
def handle_edge_release(self, event): def handle_edge_release(self, event: tk.Event):
edge = self.drawing_edge edge = self.drawing_edge
self.drawing_edge = None self.drawing_edge = None
@ -417,7 +401,7 @@ class CanvasGraph(tk.Canvas):
node_dst.edges.add(edge) node_dst.edges.add(edge)
self.core.create_link(edge, node_src, node_dst) self.core.create_link(edge, node_src, node_dst)
def select_object(self, object_id, choose_multiple=False): def select_object(self, object_id: int, choose_multiple: Optional[bool] = False):
""" """
create a bounding box when a node is selected create a bounding box when a node is selected
""" """
@ -441,19 +425,17 @@ class CanvasGraph(tk.Canvas):
def clear_selection(self): def clear_selection(self):
""" """
Clear current selection boxes. Clear current selection boxes.
:return: nothing
""" """
for _id in self.selection.values(): for _id in self.selection.values():
self.delete(_id) self.delete(_id)
self.selection.clear() self.selection.clear()
def move_selection(self, object_id, x_offset, y_offset): def move_selection(self, object_id: int, x_offset: float, y_offset: float):
select_id = self.selection.get(object_id) select_id = self.selection.get(object_id)
if select_id is not None: if select_id is not None:
self.move(select_id, x_offset, y_offset) self.move(select_id, x_offset, y_offset)
def delete_selection_objects(self): def delete_selection_objects(self) -> List[CanvasNode]:
edges = set() edges = set()
nodes = [] nodes = []
for object_id in self.selection: for object_id in self.selection:
@ -499,7 +481,7 @@ class CanvasGraph(tk.Canvas):
self.selection.clear() self.selection.clear()
return nodes return nodes
def zoom(self, event, factor=None): def zoom(self, event: tk.Event, factor: Optional[float] = None):
if not factor: if not factor:
factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT factor = ZOOM_IN if event.delta > 0 else ZOOM_OUT
event.x, event.y = self.canvasx(event.x), self.canvasy(event.y) event.x, event.y = self.canvasx(event.x), self.canvasy(event.y)
@ -517,12 +499,9 @@ class CanvasGraph(tk.Canvas):
if self.wallpaper: if self.wallpaper:
self.redraw_wallpaper() self.redraw_wallpaper()
def click_press(self, event): def click_press(self, event: tk.Event):
""" """
Start drawing an edge if mouse click is on a node Start drawing an edge if mouse click is on a node
:param event: mouse event
:return: nothing
""" """
x, y = self.canvas_xy(event) x, y = self.canvas_xy(event)
if not self.inside_canvas(x, y): if not self.inside_canvas(x, y):
@ -581,7 +560,7 @@ class CanvasGraph(tk.Canvas):
self.select_box = shape self.select_box = shape
self.clear_selection() self.clear_selection()
def ctrl_click(self, event): def ctrl_click(self, event: tk.Event):
# update cursor location # update cursor location
x, y = self.canvas_xy(event) x, y = self.canvas_xy(event)
if not self.inside_canvas(x, y): if not self.inside_canvas(x, y):
@ -599,12 +578,9 @@ class CanvasGraph(tk.Canvas):
): ):
self.select_object(selected, choose_multiple=True) self.select_object(selected, choose_multiple=True)
def click_motion(self, event): def click_motion(self, event: tk.Event):
""" """
Redraw drawing edge according to the current position of the mouse Redraw drawing edge according to the current position of the mouse
:param event: mouse event
:return: nothing
""" """
x, y = self.canvas_xy(event) x, y = self.canvas_xy(event)
if not self.inside_canvas(x, y): if not self.inside_canvas(x, y):
@ -658,7 +634,7 @@ class CanvasGraph(tk.Canvas):
if self.select_box and self.mode == GraphMode.SELECT: if self.select_box and self.mode == GraphMode.SELECT:
self.select_box.shape_motion(x, y) self.select_box.shape_motion(x, y)
def click_context(self, event): def click_context(self, event: tk.Event):
logging.info("context event: %s", self.context) logging.info("context event: %s", self.context)
if not self.context: if not self.context:
selected = self.get_selected(event) selected = self.get_selected(event)
@ -670,24 +646,22 @@ class CanvasGraph(tk.Canvas):
else: else:
self.hide_context() self.hide_context()
def press_delete(self, event): def press_delete(self, event: tk.Event):
""" """
delete selected nodes and any data that relates to it delete selected nodes and any data that relates to it
:param event:
:return:
""" """
logging.debug("press delete key") logging.debug("press delete key")
nodes = self.delete_selection_objects() nodes = self.delete_selection_objects()
self.core.delete_graph_nodes(nodes) self.core.delete_graph_nodes(nodes)
def double_click(self, event): def double_click(self, event: tk.Event):
selected = self.get_selected(event) selected = self.get_selected(event)
if selected is not None and selected in self.shapes: if selected is not None and selected in self.shapes:
shape = self.shapes[selected] shape = self.shapes[selected]
dialog = ShapeDialog(self.app, self.app, shape) dialog = ShapeDialog(self.app, self.app, shape)
dialog.show() dialog.show()
def add_node(self, x, y): def add_node(self, x: float, y: float) -> CanvasNode:
if self.selected is None or self.selected in self.shapes: if self.selected is None or self.selected in self.shapes:
actual_x, actual_y = self.get_actual_coords(x, y) actual_x, actual_y = self.get_actual_coords(x, y)
core_node = self.core.create_node( core_node = self.core.create_node(
@ -701,26 +675,28 @@ class CanvasGraph(tk.Canvas):
def width_and_height(self): def width_and_height(self):
""" """
retrieve canvas width and height in pixels retrieve canvas width and height in pixels
:return: nothing
""" """
x0, y0, x1, y1 = self.coords(self.grid) x0, y0, x1, y1 = self.coords(self.grid)
canvas_w = abs(x0 - x1) canvas_w = abs(x0 - x1)
canvas_h = abs(y0 - y1) canvas_h = abs(y0 - y1)
return canvas_w, canvas_h return canvas_w, canvas_h
def get_wallpaper_image(self): def get_wallpaper_image(self) -> Image.Image:
width = int(self.wallpaper.width * self.ratio) width = int(self.wallpaper.width * self.ratio)
height = int(self.wallpaper.height * self.ratio) height = int(self.wallpaper.height * self.ratio)
image = self.wallpaper.resize((width, height), Image.ANTIALIAS) image = self.wallpaper.resize((width, height), Image.ANTIALIAS)
return image return image
def draw_wallpaper(self, image, x=None, y=None): def draw_wallpaper(
self,
image: ImageTk.PhotoImage,
x: Optional[float] = None,
y: Optional[float] = None,
):
if x is None and y is None: if x is None and y is None:
x1, y1, x2, y2 = self.bbox(self.grid) x1, y1, x2, y2 = self.bbox(self.grid)
x = (x1 + x2) / 2 x = (x1 + x2) / 2
y = (y1 + y2) / 2 y = (y1 + y2) / 2
self.wallpaper_id = self.create_image((x, y), image=image, tags=tags.WALLPAPER) self.wallpaper_id = self.create_image((x, y), image=image, tags=tags.WALLPAPER)
self.wallpaper_drawn = image self.wallpaper_drawn = image
@ -748,8 +724,6 @@ class CanvasGraph(tk.Canvas):
def wallpaper_center(self): def wallpaper_center(self):
""" """
place the image at the center of canvas place the image at the center of canvas
:return: nothing
""" """
self.delete(self.wallpaper_id) self.delete(self.wallpaper_id)
@ -773,8 +747,6 @@ class CanvasGraph(tk.Canvas):
def wallpaper_scaled(self): def wallpaper_scaled(self):
""" """
scale image based on canvas dimension scale image based on canvas dimension
:return: nothing
""" """
self.delete(self.wallpaper_id) self.delete(self.wallpaper_id)
canvas_w, canvas_h = self.width_and_height() canvas_w, canvas_h = self.width_and_height()
@ -788,7 +760,7 @@ class CanvasGraph(tk.Canvas):
self.redraw_canvas((image.width(), image.height())) self.redraw_canvas((image.width(), image.height()))
self.draw_wallpaper(image) self.draw_wallpaper(image)
def redraw_canvas(self, dimensions=None): def redraw_canvas(self, dimensions: Optional[List[int]] = None):
logging.info("redrawing canvas to dimensions: %s", dimensions) logging.info("redrawing canvas to dimensions: %s", dimensions)
# reset scale and move back to original position # reset scale and move back to original position
@ -836,7 +808,7 @@ class CanvasGraph(tk.Canvas):
else: else:
self.itemconfig(tags.GRIDLINE, state=tk.HIDDEN) self.itemconfig(tags.GRIDLINE, state=tk.HIDDEN)
def set_wallpaper(self, filename): def set_wallpaper(self, filename: str):
logging.info("setting wallpaper: %s", filename) logging.info("setting wallpaper: %s", filename)
if filename: if filename:
img = Image.open(filename) img = Image.open(filename)
@ -849,16 +821,12 @@ class CanvasGraph(tk.Canvas):
self.wallpaper = None self.wallpaper = None
self.wallpaper_file = None self.wallpaper_file = None
def is_selection_mode(self): def is_selection_mode(self) -> bool:
return self.mode == GraphMode.SELECT return self.mode == GraphMode.SELECT
def create_edge(self, source, dest): def create_edge(self, source: CanvasNode, dest: CanvasNode):
""" """
create an edge between source node and destination node create an edge between source node and destination node
:param CanvasNode source: source node
:param CanvasNode dest: destination node
:return: nothing
""" """
if (source.id, dest.id) not in self.edges: if (source.id, dest.id) not in self.edges:
pos0 = source.core_node.position pos0 = source.core_node.position

View file

@ -20,7 +20,7 @@ NODE_TEXT_OFFSET = 5
class CanvasNode: class CanvasNode:
def __init__(self, app, x: int, y: int, core_node: core_pb2.Node, image): def __init__(self, app, x: float, y: float, core_node: core_pb2.Node, image):
self.app = app self.app = app
self.canvas = app.canvas self.canvas = app.canvas
self.image = image self.image = image
@ -70,8 +70,6 @@ class CanvasNode:
def delete_antenna(self): def delete_antenna(self):
""" """
delete one antenna delete one antenna
:return: nothing
""" """
if self.antennae: if self.antennae:
antenna_id = self.antennae.pop() antenna_id = self.antennae.pop()
@ -80,8 +78,6 @@ class CanvasNode:
def delete_antennae(self): def delete_antennae(self):
""" """
delete all antennas delete all antennas
:return: nothing
""" """
for antenna_id in self.antennae: for antenna_id in self.antennae:
self.canvas.delete(antenna_id) self.canvas.delete(antenna_id)

View file

@ -1,4 +1,5 @@
import logging import logging
from typing import List, Optional, Union
from core.gui.dialogs.shapemod import ShapeDialog from core.gui.dialogs.shapemod import ShapeDialog
from core.gui.graph import tags from core.gui.graph import tags
@ -8,16 +9,16 @@ from core.gui.graph.shapeutils import ShapeType
class AnnotationData: class AnnotationData:
def __init__( def __init__(
self, self,
text="", text: Optional[str] = "",
font="Arial", font: Optional[str] = "Arial",
font_size=12, font_size: Optional[int] = 12,
text_color="#000000", text_color: Optional[str] = "#000000",
fill_color="", fill_color: Optional[str] = "",
border_color="#000000", border_color: Optional[str] = "#000000",
border_width=1, border_width: Optional[int] = 1,
bold=False, bold: Optional[bool] = False,
italic=False, italic: Optional[bool] = False,
underline=False, underline: Optional[bool] = False,
): ):
self.text = text self.text = text
self.font = font self.font = font
@ -99,7 +100,7 @@ class Shape:
logging.error("unknown shape type: %s", self.shape_type) logging.error("unknown shape type: %s", self.shape_type)
self.created = True self.created = True
def get_font(self): def get_font(self) -> List[Union[int, str]]:
font = [self.shape_data.font, self.shape_data.font_size] font = [self.shape_data.font, self.shape_data.font_size]
if self.shape_data.bold: if self.shape_data.bold:
font.append("bold") font.append("bold")
@ -123,10 +124,10 @@ class Shape:
font=font, font=font,
) )
def shape_motion(self, x1: int, y1: int): def shape_motion(self, x1: float, y1: float):
self.canvas.coords(self.id, self.x1, self.y1, x1, y1) self.canvas.coords(self.id, self.x1, self.y1, x1, y1)
def shape_complete(self, x, y): def shape_complete(self, x: float, y: float):
for component in tags.ABOVE_SHAPE: for component in tags.ABOVE_SHAPE:
self.canvas.tag_raise(component) self.canvas.tag_raise(component)
s = ShapeDialog(self.app, self.app, self) s = ShapeDialog(self.app, self.app, self)
@ -135,7 +136,7 @@ class Shape:
def disappear(self): def disappear(self):
self.canvas.delete(self.id) self.canvas.delete(self.id)
def motion(self, x_offset: int, y_offset: int): def motion(self, x_offset: float, y_offset: float):
original_position = self.canvas.coords(self.id) original_position = self.canvas.coords(self.id)
self.canvas.move(self.id, x_offset, y_offset) self.canvas.move(self.id, x_offset, y_offset)
coords = self.canvas.coords(self.id) coords = self.canvas.coords(self.id)

View file

@ -11,13 +11,13 @@ class ShapeType(enum.Enum):
SHAPES = {ShapeType.OVAL, ShapeType.RECTANGLE} SHAPES = {ShapeType.OVAL, ShapeType.RECTANGLE}
def is_draw_shape(shape_type): def is_draw_shape(shape_type: ShapeType) -> bool:
return shape_type in SHAPES return shape_type in SHAPES
def is_shape_text(shape_type): def is_shape_text(shape_type: ShapeType) -> bool:
return shape_type == ShapeType.TEXT return shape_type == ShapeType.TEXT
def is_marker(shape_type): def is_marker(shape_type: ShapeType) -> bool:
return shape_type == ShapeType.MARKER return shape_type == ShapeType.MARKER

View file

@ -1,5 +1,6 @@
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk
from typing import Optional
from core.gui.themes import Styles from core.gui.themes import Styles
@ -30,10 +31,10 @@ class CanvasTooltip:
self.id = None self.id = None
self.tw = None self.tw = None
def on_enter(self, event=None): def on_enter(self, event: Optional[tk.Event] = None):
self.schedule() self.schedule()
def on_leave(self, event=None): def on_leave(self, event: Optional[tk.Event] = None):
self.unschedule() self.unschedule()
self.hide() self.hide()
@ -47,7 +48,7 @@ class CanvasTooltip:
if id_: if id_:
self.canvas.after_cancel(id_) self.canvas.after_cancel(id_)
def show(self, event=None): def show(self, event: Optional[tk.Event] = None):
def tip_pos_calculator(canvas, label, *, tip_delta=(10, 5), pad=(5, 3, 5, 3)): def tip_pos_calculator(canvas, label, *, tip_delta=(10, 5), pad=(5, 3, 5, 3)):
c = canvas c = canvas
s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight() s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight()

View file

@ -1,8 +1,10 @@
import logging import logging
import random import random
from typing import Optional, Set
from netaddr import IPNetwork from netaddr import IPNetwork
from core.gui.graph.node import CanvasNode
from core.gui.nodeutils import NodeUtils from core.gui.nodeutils import NodeUtils
@ -11,7 +13,9 @@ def random_mac():
class InterfaceManager: class InterfaceManager:
def __init__(self, app, address="10.0.0.0", mask=24): def __init__(
self, app, address: Optional[str] = "10.0.0.0", mask: Optional[int] = 24
):
self.app = app self.app = app
self.mask = mask self.mask = mask
self.base_prefix = max(self.mask - 8, 0) self.base_prefix = max(self.mask - 8, 0)
@ -38,7 +42,7 @@ class InterfaceManager:
def reset(self): def reset(self):
self.current_subnet = None self.current_subnet = None
def get_ips(self, node_id): def get_ips(self, node_id: int):
ip4 = self.current_subnet[node_id] ip4 = self.current_subnet[node_id]
ip6 = ip4.ipv6() ip6 = ip4.ipv6()
prefix = self.current_subnet.prefixlen prefix = self.current_subnet.prefixlen
@ -48,7 +52,9 @@ class InterfaceManager:
def get_subnet(cls, interface): def get_subnet(cls, interface):
return IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr return IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr
def determine_subnet(self, canvas_src_node, canvas_dst_node): def determine_subnet(
self, canvas_src_node: CanvasNode, canvas_dst_node: CanvasNode
):
src_node = canvas_src_node.core_node src_node = canvas_src_node.core_node
dst_node = canvas_dst_node.core_node dst_node = canvas_dst_node.core_node
is_src_container = NodeUtils.is_container_node(src_node.type) is_src_container = NodeUtils.is_container_node(src_node.type)
@ -70,7 +76,7 @@ class InterfaceManager:
else: else:
logging.info("ignoring subnet change for link between network nodes") logging.info("ignoring subnet change for link between network nodes")
def find_subnet(self, canvas_node, visited=None): def find_subnet(self, canvas_node: CanvasNode, visited: Optional[Set[int]] = None):
logging.info("finding subnet for node: %s", canvas_node.core_node.name) logging.info("finding subnet for node: %s", canvas_node.core_node.name)
canvas = self.app.canvas canvas = self.app.canvas
cidr = None cidr = None

View file

@ -32,14 +32,14 @@ class MenuAction:
self.app = app self.app = app
self.canvas = app.canvas self.canvas = app.canvas
def cleanup_old_session(self, quitapp: bool = False): def cleanup_old_session(self, quitapp: Optional[bool] = False):
logging.info("cleaning up old session") logging.info("cleaning up old session")
self.app.core.stop_session() self.app.core.stop_session()
self.app.core.delete_session() self.app.core.delete_session()
# if quitapp: # if quitapp:
# self.app.quit() # self.app.quit()
def prompt_save_running_session(self, quitapp: bool = False): def prompt_save_running_session(self, quitapp: Optional[bool] = False):
""" """
Prompt use to stop running session before application is closed Prompt use to stop running session before application is closed

View file

@ -13,10 +13,6 @@ class Menubar(tk.Menu):
def __init__(self, master, app, cnf={}, **kwargs): def __init__(self, master, app, cnf={}, **kwargs):
""" """
Create a CoreMenubar instance Create a CoreMenubar instance
:param master:
:param tkinter.Menu menubar: menubar object
:param coretk.app.Application app: application object
""" """
super().__init__(master, cnf, **kwargs) super().__init__(master, cnf, **kwargs)
self.master.config(menu=self) self.master.config(menu=self)
@ -27,8 +23,6 @@ class Menubar(tk.Menu):
def draw(self): def draw(self):
""" """
Create core menubar and bind the hot keys to their matching command Create core menubar and bind the hot keys to their matching command
:return: nothing
""" """
self.draw_file_menu() self.draw_file_menu()
self.draw_edit_menu() self.draw_edit_menu()
@ -42,8 +36,6 @@ class Menubar(tk.Menu):
def draw_file_menu(self): def draw_file_menu(self):
""" """
Create file menu Create file menu
:return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command( menu.add_command(
@ -81,8 +73,6 @@ class Menubar(tk.Menu):
def draw_edit_menu(self): def draw_edit_menu(self):
""" """
Create edit menu Create edit menu
:return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command(label="Preferences", command=self.menuaction.gui_preferences) menu.add_command(label="Preferences", command=self.menuaction.gui_preferences)
@ -112,8 +102,6 @@ class Menubar(tk.Menu):
def draw_canvas_menu(self): def draw_canvas_menu(self):
""" """
Create canvas menu Create canvas menu
:return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command( menu.add_command(
@ -136,8 +124,6 @@ class Menubar(tk.Menu):
def draw_view_menu(self): def draw_view_menu(self):
""" """
Create view menu Create view menu
:return: nothing
""" """
view_menu = tk.Menu(self) view_menu = tk.Menu(self)
self.create_show_menu(view_menu) self.create_show_menu(view_menu)
@ -152,9 +138,6 @@ class Menubar(tk.Menu):
def create_show_menu(self, view_menu: tk.Menu): def create_show_menu(self, view_menu: tk.Menu):
""" """
Create the menu items in View/Show Create the menu items in View/Show
:param tkinter.Menu view_menu: the view menu
:return: nothing
""" """
menu = tk.Menu(view_menu) menu = tk.Menu(view_menu)
menu.add_command(label="All", state=tk.DISABLED) menu.add_command(label="All", state=tk.DISABLED)
@ -172,9 +155,6 @@ class Menubar(tk.Menu):
def create_experimental_menu(self, tools_menu: tk.Menu): def create_experimental_menu(self, tools_menu: tk.Menu):
""" """
Create experimental menu item and the sub menu items inside Create experimental menu item and the sub menu items inside
:param tkinter.Menu tools_menu: tools menu
:return: nothing
""" """
menu = tk.Menu(tools_menu) menu = tk.Menu(tools_menu)
menu.add_command(label="Plugins...", state=tk.DISABLED) menu.add_command(label="Plugins...", state=tk.DISABLED)
@ -185,9 +165,6 @@ class Menubar(tk.Menu):
def create_random_menu(self, topology_generator_menu: tk.Menu): def create_random_menu(self, topology_generator_menu: tk.Menu):
""" """
Create random menu item and the sub menu items inside Create random menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
# list of number of random nodes to create # list of number of random nodes to create
@ -200,9 +177,6 @@ class Menubar(tk.Menu):
def create_grid_menu(self, topology_generator_menu: tk.Menu): def create_grid_menu(self, topology_generator_menu: tk.Menu):
""" """
Create grid menu item and the sub menu items inside Create grid menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology_generator_menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
# list of number of nodes to create # list of number of nodes to create
@ -215,9 +189,6 @@ class Menubar(tk.Menu):
def create_connected_grid_menu(self, topology_generator_menu: tk.Menu): def create_connected_grid_menu(self, topology_generator_menu: tk.Menu):
""" """
Create connected grid menu items and the sub menu items inside Create connected grid menu items and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
for i in range(1, 11, 1): for i in range(1, 11, 1):
@ -232,9 +203,6 @@ class Menubar(tk.Menu):
def create_chain_menu(self, topology_generator_menu: tk.Menu): def create_chain_menu(self, topology_generator_menu: tk.Menu):
""" """
Create chain menu item and the sub menu items inside Create chain menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
# number of nodes to create # number of nodes to create
@ -247,9 +215,6 @@ class Menubar(tk.Menu):
def create_star_menu(self, topology_generator_menu: tk.Menu): def create_star_menu(self, topology_generator_menu: tk.Menu):
""" """
Create star menu item and the sub menu items inside Create star menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
for i in range(3, 26, 1): for i in range(3, 26, 1):
@ -260,9 +225,6 @@ class Menubar(tk.Menu):
def create_cycle_menu(self, topology_generator_menu: tk.Menu): def create_cycle_menu(self, topology_generator_menu: tk.Menu):
""" """
Create cycle menu item and the sub items inside Create cycle menu item and the sub items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
for i in range(3, 25, 1): for i in range(3, 25, 1):
@ -273,9 +235,6 @@ class Menubar(tk.Menu):
def create_wheel_menu(self, topology_generator_menu: tk.Menu): def create_wheel_menu(self, topology_generator_menu: tk.Menu):
""" """
Create wheel menu item and the sub menu items inside Create wheel menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
for i in range(4, 26, 1): for i in range(4, 26, 1):
@ -286,9 +245,6 @@ class Menubar(tk.Menu):
def create_cube_menu(self, topology_generator_menu: tk.Menu): def create_cube_menu(self, topology_generator_menu: tk.Menu):
""" """
Create cube menu item and the sub menu items inside Create cube menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
for i in range(2, 7, 1): for i in range(2, 7, 1):
@ -299,9 +255,6 @@ class Menubar(tk.Menu):
def create_clique_menu(self, topology_generator_menu: tk.Menu): def create_clique_menu(self, topology_generator_menu: tk.Menu):
""" """
Create clique menu item and the sub menu items inside Create clique menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology generator menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
for i in range(3, 25, 1): for i in range(3, 25, 1):
@ -312,9 +265,6 @@ class Menubar(tk.Menu):
def create_bipartite_menu(self, topology_generator_menu: tk.Menu): def create_bipartite_menu(self, topology_generator_menu: tk.Menu):
""" """
Create bipartite menu item and the sub menu items inside Create bipartite menu item and the sub menu items inside
:param tkinter.Menu topology_generator_menu: topology_generator_menu
:return: nothing
""" """
menu = tk.Menu(topology_generator_menu) menu = tk.Menu(topology_generator_menu)
temp = 24 temp = 24
@ -331,10 +281,6 @@ class Menubar(tk.Menu):
def create_topology_generator_menu(self, tools_menu: tk.Menu): def create_topology_generator_menu(self, tools_menu: tk.Menu):
""" """
Create topology menu item and its sub menu items Create topology menu item and its sub menu items
:param tkinter.Menu tools_menu: tools menu
:return: nothing
""" """
menu = tk.Menu(tools_menu) menu = tk.Menu(tools_menu)
self.create_random_menu(menu) self.create_random_menu(menu)
@ -352,8 +298,6 @@ class Menubar(tk.Menu):
def draw_tools_menu(self): def draw_tools_menu(self):
""" """
Create tools menu Create tools menu
:return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command(label="Auto rearrange all", state=tk.DISABLED) menu.add_command(label="Auto rearrange all", state=tk.DISABLED)
@ -374,9 +318,6 @@ class Menubar(tk.Menu):
def create_observer_widgets_menu(self, widget_menu: tk.Menu): def create_observer_widgets_menu(self, widget_menu: tk.Menu):
""" """
Create observer widget menu item and create the sub menu items inside Create observer widget menu item and create the sub menu items inside
:param tkinter.Menu widget_menu: widget_menu
:return: nothing
""" """
var = tk.StringVar(value="none") var = tk.StringVar(value="none")
menu = tk.Menu(widget_menu) menu = tk.Menu(widget_menu)
@ -412,9 +353,6 @@ class Menubar(tk.Menu):
def create_adjacency_menu(self, widget_menu: tk.Menu): def create_adjacency_menu(self, widget_menu: tk.Menu):
""" """
Create adjacency menu item and the sub menu items inside Create adjacency menu item and the sub menu items inside
:param tkinter.Menu widget_menu: widget menu
:return: nothing
""" """
menu = tk.Menu(widget_menu) menu = tk.Menu(widget_menu)
menu.add_command(label="OSPFv2", state=tk.DISABLED) menu.add_command(label="OSPFv2", state=tk.DISABLED)
@ -426,8 +364,6 @@ class Menubar(tk.Menu):
def draw_widgets_menu(self): def draw_widgets_menu(self):
""" """
Create widget menu Create widget menu
:return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
self.create_observer_widgets_menu(menu) self.create_observer_widgets_menu(menu)
@ -443,8 +379,6 @@ class Menubar(tk.Menu):
def draw_session_menu(self): def draw_session_menu(self):
""" """
Create session menu Create session menu
:return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command( menu.add_command(
@ -461,8 +395,6 @@ class Menubar(tk.Menu):
def draw_help_menu(self): def draw_help_menu(self):
""" """
Create help menu Create help menu
:return: nothing
""" """
menu = tk.Menu(self) menu = tk.Menu(self)
menu.add_command( menu.add_command(

View file

@ -53,31 +53,31 @@ class NodeUtils:
ANTENNA_ICON = None ANTENNA_ICON = None
@classmethod @classmethod
def is_ignore_node(cls, node_type): def is_ignore_node(cls, node_type) -> bool:
return node_type in cls.IGNORE_NODES return node_type in cls.IGNORE_NODES
@classmethod @classmethod
def is_container_node(cls, node_type): def is_container_node(cls, node_type) -> bool:
return node_type in cls.CONTAINER_NODES return node_type in cls.CONTAINER_NODES
@classmethod @classmethod
def is_model_node(cls, node_type): def is_model_node(cls, node_type) -> bool:
return node_type == NodeType.DEFAULT return node_type == NodeType.DEFAULT
@classmethod @classmethod
def is_image_node(cls, node_type): def is_image_node(cls, node_type) -> bool:
return node_type in cls.IMAGE_NODES return node_type in cls.IMAGE_NODES
@classmethod @classmethod
def is_wireless_node(cls, node_type): def is_wireless_node(cls, node_type) -> bool:
return node_type in cls.WIRELESS_NODES return node_type in cls.WIRELESS_NODES
@classmethod @classmethod
def is_rj45_node(cls, node_type): def is_rj45_node(cls, node_type) -> bool:
return node_type in cls.RJ45_NODES return node_type in cls.RJ45_NODES
@classmethod @classmethod
def node_icon(cls, node_type, model): def node_icon(cls, node_type, model: str) -> bool:
if model == "": if model == "":
model = None model = None
return cls.NODE_ICONS[(node_type, model)] return cls.NODE_ICONS[(node_type, model)]

View file

@ -1,4 +1,6 @@
"status bar" """
status bar
"""
import tkinter as tk import tkinter as tk
from tkinter import ttk from tkinter import ttk

View file

@ -4,6 +4,9 @@ import tkinter as tk
from functools import partial from functools import partial
from tkinter import messagebox, ttk from tkinter import messagebox, ttk
from tkinter.font import Font from tkinter.font import Font
from typing import Callable
from PIL import ImageTk
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from core.gui.dialogs.customnodes import CustomNodesDialog from core.gui.dialogs.customnodes import CustomNodesDialog
@ -196,7 +199,9 @@ class Toolbar(ttk.Frame):
self.wait_window(picker) self.wait_window(picker)
self.app.unbind_all("<ButtonRelease-1>") self.app.unbind_all("<ButtonRelease-1>")
def create_picker_button(self, image, func, frame: ttk.Frame, label: str): def create_picker_button(
self, image: ImageTk.PhotoImage, func: Callable, frame: ttk.Frame, label: str
):
""" """
Create button and put it on the frame Create button and put it on the frame
@ -204,7 +209,6 @@ class Toolbar(ttk.Frame):
:param func: the command that is executed when button is clicked :param func: the command that is executed when button is clicked
:param tkinter.Frame frame: frame that contains the button :param tkinter.Frame frame: frame that contains the button
:param str label: button label :param str label: button label
:return: nothing
""" """
button = ttk.Button( button = ttk.Button(
frame, image=image, text=label, compound=tk.TOP, style=Styles.picker_button frame, image=image, text=label, compound=tk.TOP, style=Styles.picker_button
@ -213,7 +217,9 @@ class Toolbar(ttk.Frame):
button.bind("<ButtonRelease-1>", lambda e: func()) button.bind("<ButtonRelease-1>", lambda e: func())
button.grid(pady=1) button.grid(pady=1)
def create_button(self, frame: ttk.Frame, image, func, tooltip: str): def create_button(
self, frame: ttk.Frame, image: ImageTk.PhotoImage, func: Callable, tooltip: str
):
button = ttk.Button(frame, image=image, command=func) button = ttk.Button(frame, image=image, command=func)
button.image = image button.image = image
button.grid(sticky="ew") button.grid(sticky="ew")
@ -234,8 +240,6 @@ class Toolbar(ttk.Frame):
""" """
Start session handler redraw buttons, send node and link messages to grpc Start session handler redraw buttons, send node and link messages to grpc
server. server.
:return: nothing
""" """
self.app.canvas.hide_context() self.app.canvas.hide_context()
self.app.statusbar.progress_bar.start(5) self.app.statusbar.progress_bar.start(5)
@ -299,8 +303,6 @@ class Toolbar(ttk.Frame):
def create_node_button(self): def create_node_button(self):
""" """
Create network layer button Create network layer button
:return: nothing
""" """
image = icon(ImageEnum.ROUTER) image = icon(ImageEnum.ROUTER)
self.node_button = ttk.Button( self.node_button = ttk.Button(
@ -313,8 +315,6 @@ class Toolbar(ttk.Frame):
def draw_network_picker(self): def draw_network_picker(self):
""" """
Draw the options for link-layer button. Draw the options for link-layer button.
:return: nothing
""" """
self.hide_pickers() self.hide_pickers()
self.network_picker = ttk.Frame(self.master) self.network_picker = ttk.Frame(self.master)
@ -338,8 +338,6 @@ class Toolbar(ttk.Frame):
""" """
Create link-layer node button and the options that represent different Create link-layer node button and the options that represent different
link-layer node types. link-layer node types.
:return: nothing
""" """
image = icon(ImageEnum.HUB) image = icon(ImageEnum.HUB)
self.network_button = ttk.Button( self.network_button = ttk.Button(
@ -352,8 +350,6 @@ class Toolbar(ttk.Frame):
def draw_annotation_picker(self): def draw_annotation_picker(self):
""" """
Draw the options for marker button. Draw the options for marker button.
:return: nothing
""" """
self.hide_pickers() self.hide_pickers()
self.annotation_picker = ttk.Frame(self.master) self.annotation_picker = ttk.Frame(self.master)
@ -380,8 +376,6 @@ class Toolbar(ttk.Frame):
def create_annotation_button(self): def create_annotation_button(self):
""" """
Create marker button and options that represent different marker types Create marker button and options that represent different marker types
:return: nothing
""" """
image = icon(ImageEnum.MARKER) image = icon(ImageEnum.MARKER)
self.annotation_button = ttk.Button( self.annotation_button = ttk.Button(
@ -418,8 +412,6 @@ class Toolbar(ttk.Frame):
def click_stop(self): def click_stop(self):
""" """
redraw buttons on the toolbar, send node and link messages to grpc server redraw buttons on the toolbar, send node and link messages to grpc server
:return: nothing
""" """
self.app.canvas.hide_context() self.app.canvas.hide_context()
self.app.statusbar.progress_bar.start(5) self.app.statusbar.progress_bar.start(5)

View file

@ -40,7 +40,7 @@ class InputValidation:
if value == "": if value == "":
event.widget.insert(tk.END, default) event.widget.insert(tk.END, default)
def check_positive_int(self, s: str): def check_positive_int(self, s: str) -> bool:
if len(s) == 0: if len(s) == 0:
return True return True
try: try:
@ -51,7 +51,7 @@ class InputValidation:
except ValueError: except ValueError:
return False return False
def check_positive_float(self, s: str): def check_positive_float(self, s: str) -> bool:
if len(s) == 0: if len(s) == 0:
return True return True
try: try:
@ -62,7 +62,7 @@ class InputValidation:
except ValueError: except ValueError:
return False return False
def check_node_name(self, s: str): def check_node_name(self, s: str) -> bool:
if len(s) < 0: if len(s) < 0:
return False return False
if len(s) == 0: if len(s) == 0:
@ -72,7 +72,7 @@ class InputValidation:
return False return False
return True return True
def check_canvas_int(self, s: str): def check_canvas_int(self, s: str) -> bool:
if len(s) == 0: if len(s) == 0:
return True return True
try: try:
@ -83,7 +83,7 @@ class InputValidation:
except ValueError: except ValueError:
return False return False
def check_canvas_float(self, s: str): def check_canvas_float(self, s: str) -> bool:
if not s: if not s:
return True return True
try: try:
@ -94,7 +94,7 @@ class InputValidation:
except ValueError: except ValueError:
return False return False
def check_ip4(self, s: str): def check_ip4(self, s: str) -> bool:
if not s: if not s:
return True return True
pat = re.compile("^([0-9]+[.])*[0-9]*$") pat = re.compile("^([0-9]+[.])*[0-9]*$")
@ -113,7 +113,7 @@ class InputValidation:
else: else:
return False return False
def check_rbg(self, s: str): def check_rbg(self, s: str) -> bool:
if not s: if not s:
return True return True
if s.startswith("0") and len(s) >= 2: if s.startswith("0") and len(s) >= 2:
@ -127,7 +127,7 @@ class InputValidation:
except ValueError: except ValueError:
return False return False
def check_hex(self, s: str): def check_hex(self, s: str) -> bool:
if not s: if not s:
return True return True
pat = re.compile("^([#]([0-9]|[a-f])+)$|^[#]$") pat = re.compile("^([#]([0-9]|[a-f])+)$|^[#]$")

View file

@ -1,6 +1,7 @@
import logging import logging
import tkinter as tk import tkinter as tk
from functools import partial from functools import partial
from pathlib import PosixPath
from tkinter import filedialog, font, ttk from tkinter import filedialog, font, ttk
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
@ -19,7 +20,7 @@ INT_TYPES = {
} }
def file_button_click(value, parent): def file_button_click(value: tk.StringVar, parent: tk.Widget):
file_path = filedialog.askopenfilename(title="Select File", parent=parent) file_path = filedialog.askopenfilename(title="Select File", parent=parent)
if file_path: if file_path:
value.set(file_path) value.set(file_path)
@ -49,13 +50,13 @@ class FrameScroll(ttk.Frame):
self.frame.bind("<Configure>", self._configure_frame) self.frame.bind("<Configure>", self._configure_frame)
self.canvas.bind("<Configure>", self._configure_canvas) self.canvas.bind("<Configure>", self._configure_canvas)
def _configure_frame(self, event): def _configure_frame(self, event: tk.Event):
req_width = self.frame.winfo_reqwidth() req_width = self.frame.winfo_reqwidth()
if req_width != self.canvas.winfo_reqwidth(): if req_width != self.canvas.winfo_reqwidth():
self.canvas.configure(width=req_width) self.canvas.configure(width=req_width)
self.canvas.configure(scrollregion=self.canvas.bbox("all")) self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def _configure_canvas(self, event): def _configure_canvas(self, event: tk.Event):
self.canvas.itemconfig(self.frame_id, width=event.width) self.canvas.itemconfig(self.frame_id, width=event.width)
def clear(self): def clear(self):
@ -238,7 +239,7 @@ class Spinbox(ttk.Entry):
self.tk.call(self._w, "set", value) self.tk.call(self._w, "set", value)
def image_chooser(parent, path): def image_chooser(parent: tk.Widget, path: PosixPath):
return filedialog.askopenfilename( return filedialog.askopenfilename(
parent=parent, parent=parent,
initialdir=str(path), initialdir=str(path),