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

View file

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

View file

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

View file

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

View file

@ -31,7 +31,7 @@ class ColorPickerDialog(Dialog):
self.draw()
self.set_bindings()
def askcolor(self):
def askcolor(self) -> str:
self.show()
return self.color
@ -175,12 +175,9 @@ class ColorPickerDialog(Dialog):
self.color = self.hex.get()
self.destroy()
def get_hex(self):
def get_hex(self) -> str:
"""
convert current RGB values into hex color
:rtype: str
:return: hex color
"""
red = self.red_entry.get()
blue = self.blue_entry.get()
@ -210,35 +207,31 @@ class ColorPickerDialog(Dialog):
self.set_entry(red, green, blue)
self.set_scale(red, green, blue)
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())
self.focus = "rgb"
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.green_scale.set(green)
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.green.set(green)
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.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):
def get_rgb(self, hex_code: str) -> [int, int, int]:
"""
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:
red = hex_code[1]

View file

@ -5,6 +5,7 @@ copy service config dialog
import logging
import tkinter as tk
from tkinter import ttk
from typing import Tuple
from core.gui.dialogs.dialog import Dialog
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.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_name = self.tree.item(service_tree_id)["text"]
node_tree_id = self.tree.parent(service_tree_id)

View file

@ -71,7 +71,7 @@ class ServicesSelectDialog(Dialog):
# trigger group change
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()
if selection:
index = selection[0]
@ -81,7 +81,7 @@ class ServicesSelectDialog(Dialog):
checked = name in self.current_services
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:
self.current_services.add(name)
elif not var.get() and name in self.current_services:

View file

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

View file

@ -116,8 +116,6 @@ class EmaneConfigDialog(Dialog):
def draw_emane_configuration(self):
"""
draw the main frame for emane configuration
:return: nothing
"""
label = ttk.Label(
self.top,
@ -143,8 +141,6 @@ class EmaneConfigDialog(Dialog):
def draw_emane_models(self):
"""
create a combobox that has all the known emane models
:return: nothing
"""
frame = ttk.Frame(self.top)
frame.grid(sticky="ew", pady=PADY)
@ -210,8 +206,6 @@ class EmaneConfigDialog(Dialog):
def click_model_config(self):
"""
draw emane model configuration
:return: nothing
"""
model_name = self.emane_model.get()
logging.info("configuring emane model: %s", model_name)
@ -220,12 +214,9 @@ class EmaneConfigDialog(Dialog):
)
dialog.show()
def emane_model_change(self, event):
def emane_model_change(self, event: tk.Event):
"""
update emane model options button
:param event:
:return: nothing
"""
model_name = self.emane_model.get()
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.grid(row=0, column=1, sticky="ew")
def state_change(self, event):
def state_change(self, event: tk.Event):
state_name = self.state.get()
self.name.set(f"{state_name.lower()}_hook.sh")
def set(self, hook):
def set(self, hook: core_pb2.Hook):
self.hook = hook
self.name.set(hook.file)
self.codetext.text.delete(1.0, tk.END)
@ -140,7 +140,7 @@ class HooksDialog(Dialog):
self.edit_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():
index = self.listbox.curselection()[0]
self.selected = self.listbox.get(index)

View file

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

View file

@ -53,13 +53,13 @@ class MarkerDialog(Dialog):
for i in canvas.find_withtag("marker"):
canvas.delete(i)
def change_color(self, event):
def change_color(self, event: tk.Event):
color_picker = ColorPickerDialog(self, self.app, self.color)
color = color_picker.askcolor()
event.widget.configure(background=color)
self.color = color
def change_thickness(self, event):
def change_thickness(self, event: tk.Event):
self.radius = self.marker_thickness.get()
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
def mac_auto(is_auto, entry):
def mac_auto(is_auto, entry: ttk.Entry):
logging.info("mac auto clicked")
if is_auto.get():
logging.info("disabling mac")
@ -217,7 +217,7 @@ 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, 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.show()
@ -248,7 +248,7 @@ class NodeConfigDialog(Dialog):
self.canvas_node.redraw()
self.destroy()
def interface_select(self, event):
def interface_select(self, event: tk.Event):
listbox = event.widget
cur = listbox.curselection()
if cur:

View file

@ -87,7 +87,7 @@ class NodeServiceDialog(Dialog):
# trigger group change
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()
if selection:
index = selection[0]
@ -97,7 +97,7 @@ class NodeServiceDialog(Dialog):
checked = name in self.current_services
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:
self.current_services.add(name)
elif not var.get() and name in self.current_services:
@ -150,7 +150,7 @@ class NodeServiceDialog(Dialog):
checkbutton.invoke()
return
def is_custom_service(self, service):
def is_custom_service(self, service: str) -> bool:
service_configs = self.app.core.service_configs
file_configs = self.app.core.file_configs
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.delete_button.config(state=tk.DISABLED)
def handle_observer_change(self, event):
def handle_observer_change(self, event: tk.Event):
selection = self.observers.curselection()
if selection:
self.selected_index = selection[0]

View file

@ -72,7 +72,7 @@ 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):
def theme_change(self, event: tk.Event):
theme = self.theme.get()
logging.info("changing theme: %s", theme)
self.app.style.theme_use(theme)

View file

@ -155,7 +155,7 @@ class ServersDialog(Dialog):
self.save_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()
if selection:
self.selected_index = selection[0]

View file

@ -1,6 +1,7 @@
"Service configuration dialog"
import tkinter as tk
from tkinter import ttk
from typing import List
import grpc
@ -345,7 +346,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, event):
def add_filename(self, event: tk.Event):
# not worry about it for now
return
frame_contains_button = event.widget.master
@ -354,7 +355,7 @@ class ServiceConfigDialog(Dialog):
if filename not in combobox["values"]:
combobox["values"] += (filename,)
def delete_filename(self, event):
def delete_filename(self, event: tk.Event):
# not worry about it for now
return
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.set("")
def add_command(self, event):
def add_command(self, event: tk.Event):
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()
@ -375,7 +376,7 @@ class ServiceConfigDialog(Dialog):
return
listbox.insert(tk.END, command_to_add)
def update_entry(self, event):
def update_entry(self, event: tk.Event):
listbox = event.widget
current_selection = listbox.curselection()
if len(current_selection) > 0:
@ -386,7 +387,7 @@ class ServiceConfigDialog(Dialog):
entry.delete(0, "end")
entry.insert(0, cmd)
def delete_command(self, event):
def delete_command(self, event: tk.Event):
button = event.widget
frame_contains_button = button.master
listbox = frame_contains_button.master.grid_slaves(row=1, column=0)[0].listbox
@ -439,13 +440,13 @@ class ServiceConfigDialog(Dialog):
show_grpc_error(e)
self.destroy()
def display_service_file_data(self, event):
def display_service_file_data(self, event: tk.Event):
combobox = event.widget
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):
def update_temp_service_file_data(self, event: tk.Event):
scrolledtext = event.widget
filename = self.filename_combobox.get()
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.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:
commands.append(cmd)
listbox.insert(tk.END, cmd)

View file

@ -1,6 +1,7 @@
import logging
import tkinter as tk
from tkinter import ttk
from typing import Iterable
import grpc
@ -21,7 +22,7 @@ class SessionsDialog(Dialog):
self.sessions = self.get_sessions()
self.draw()
def get_sessions(self):
def get_sessions(self) -> Iterable[core_pb2.SessionSummary]:
try:
response = self.app.core.client.get_sessions()
logging.info("sessions: %s", response)
@ -40,7 +41,6 @@ class SessionsDialog(Dialog):
def draw_description(self):
"""
write a short description
:return: nothing
"""
label = ttk.Label(
self.top,
@ -129,7 +129,7 @@ class SessionsDialog(Dialog):
self.app.core.create_new_session()
self.destroy()
def click_select(self, event):
def click_select(self, event: tk.Event):
item = self.tree.selection()
session_id = int(self.tree.item(item, "text"))
self.selected = True
@ -138,8 +138,6 @@ class SessionsDialog(Dialog):
def click_connect(self):
"""
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:
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
session down.
:return: nothing
"""
if self.selected and self.selected_id is not None:
self.shutdown_session(self.selected_id)
@ -162,18 +158,18 @@ class SessionsDialog(Dialog):
else:
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)
task = BackgroundTask(self.app, self.app.core.join_session, args=(session_id,))
task.start()
self.destroy()
def on_selected(self, event):
def on_selected(self, event: tk.Event):
item = self.tree.selection()
sid = int(self.tree.item(item, "text"))
self.join_session(sid)
def shutdown_session(self, sid):
def shutdown_session(self, sid: int):
self.app.core.stop_session(sid)
self.click_new()
self.destroy()

View file

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

View file

@ -14,7 +14,14 @@ EDGE_COLOR = "#ff0000"
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.src = src
self.dst = dst
@ -35,11 +42,6 @@ class CanvasEdge:
def __init__(self, x1: int, y1: int, x2: int, y2: int, src: int, canvas):
"""
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
"""
self.src = src
@ -67,7 +69,7 @@ class CanvasEdge:
self.link = link
self.draw_labels()
def get_coordinates(self):
def get_coordinates(self) -> [int, int, int, int]:
x1, y1, x2, y2 = self.canvas.coords(self.id)
v1 = x2 - x1
v2 = y2 - y1
@ -79,7 +81,7 @@ class CanvasEdge:
y2 = y2 - uy
return x1, y1, x2, y2
def get_midpoint(self):
def get_midpoint(self) -> [float, float]:
x1, y1, x2, y2 = self.canvas.coords(self.id)
x = (x1 + x2) / 2
y = (y1 + y2) / 2
@ -119,8 +121,6 @@ class CanvasEdge:
def update_labels(self):
"""
Move edge labels based on current position.
:return: nothing
"""
x1, y1, x2, y2 = self.get_coordinates()
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.dst)
def is_wireless(self):
def is_wireless(self) -> [bool, bool]:
src_node = self.canvas.nodes[self.src]
dst_node = self.canvas.nodes[self.dst]
src_node_type = src_node.core_node.type
@ -184,7 +184,6 @@ class CanvasEdge:
dst_node.add_antenna()
elif not is_src_wireless and is_dst_wireless:
src_node.add_antenna()
# TODO: remove this? dont allow linking wireless nodes?
else:
src_node.add_antenna()

View file

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

View file

@ -20,7 +20,7 @@ NODE_TEXT_OFFSET = 5
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.canvas = app.canvas
self.image = image
@ -70,8 +70,6 @@ class CanvasNode:
def delete_antenna(self):
"""
delete one antenna
:return: nothing
"""
if self.antennae:
antenna_id = self.antennae.pop()
@ -80,8 +78,6 @@ class CanvasNode:
def delete_antennae(self):
"""
delete all antennas
:return: nothing
"""
for antenna_id in self.antennae:
self.canvas.delete(antenna_id)

View file

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

View file

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

View file

@ -1,5 +1,6 @@
import tkinter as tk
from tkinter import ttk
from typing import Optional
from core.gui.themes import Styles
@ -30,10 +31,10 @@ class CanvasTooltip:
self.id = None
self.tw = None
def on_enter(self, event=None):
def on_enter(self, event: Optional[tk.Event] = None):
self.schedule()
def on_leave(self, event=None):
def on_leave(self, event: Optional[tk.Event] = None):
self.unschedule()
self.hide()
@ -47,7 +48,7 @@ class CanvasTooltip:
if 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)):
c = canvas
s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight()

View file

@ -1,8 +1,10 @@
import logging
import random
from typing import Optional, Set
from netaddr import IPNetwork
from core.gui.graph.node import CanvasNode
from core.gui.nodeutils import NodeUtils
@ -11,7 +13,9 @@ def random_mac():
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.mask = mask
self.base_prefix = max(self.mask - 8, 0)
@ -38,7 +42,7 @@ class InterfaceManager:
def reset(self):
self.current_subnet = None
def get_ips(self, node_id):
def get_ips(self, node_id: int):
ip4 = self.current_subnet[node_id]
ip6 = ip4.ipv6()
prefix = self.current_subnet.prefixlen
@ -48,7 +52,9 @@ class InterfaceManager:
def get_subnet(cls, interface):
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
dst_node = canvas_dst_node.core_node
is_src_container = NodeUtils.is_container_node(src_node.type)
@ -70,7 +76,7 @@ class InterfaceManager:
else:
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)
canvas = self.app.canvas
cidr = None

View file

@ -32,14 +32,14 @@ class MenuAction:
self.app = app
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")
self.app.core.stop_session()
self.app.core.delete_session()
# if quitapp:
# 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

View file

@ -13,10 +13,6 @@ class Menubar(tk.Menu):
def __init__(self, master, app, cnf={}, **kwargs):
"""
Create a CoreMenubar instance
:param master:
:param tkinter.Menu menubar: menubar object
:param coretk.app.Application app: application object
"""
super().__init__(master, cnf, **kwargs)
self.master.config(menu=self)
@ -27,8 +23,6 @@ class Menubar(tk.Menu):
def draw(self):
"""
Create core menubar and bind the hot keys to their matching command
:return: nothing
"""
self.draw_file_menu()
self.draw_edit_menu()
@ -42,8 +36,6 @@ class Menubar(tk.Menu):
def draw_file_menu(self):
"""
Create file menu
:return: nothing
"""
menu = tk.Menu(self)
menu.add_command(
@ -81,8 +73,6 @@ class Menubar(tk.Menu):
def draw_edit_menu(self):
"""
Create edit menu
:return: nothing
"""
menu = tk.Menu(self)
menu.add_command(label="Preferences", command=self.menuaction.gui_preferences)
@ -112,8 +102,6 @@ class Menubar(tk.Menu):
def draw_canvas_menu(self):
"""
Create canvas menu
:return: nothing
"""
menu = tk.Menu(self)
menu.add_command(
@ -136,8 +124,6 @@ class Menubar(tk.Menu):
def draw_view_menu(self):
"""
Create view menu
:return: nothing
"""
view_menu = tk.Menu(self)
self.create_show_menu(view_menu)
@ -152,9 +138,6 @@ class Menubar(tk.Menu):
def create_show_menu(self, view_menu: tk.Menu):
"""
Create the menu items in View/Show
:param tkinter.Menu view_menu: the view menu
:return: nothing
"""
menu = tk.Menu(view_menu)
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):
"""
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.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):
"""
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)
# 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):
"""
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)
# 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):
"""
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)
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):
"""
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)
# number of nodes to create
@ -247,9 +215,6 @@ class Menubar(tk.Menu):
def create_star_menu(self, topology_generator_menu: tk.Menu):
"""
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)
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):
"""
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)
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):
"""
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)
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):
"""
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)
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):
"""
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)
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):
"""
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)
temp = 24
@ -331,10 +281,6 @@ class Menubar(tk.Menu):
def create_topology_generator_menu(self, tools_menu: tk.Menu):
"""
Create topology menu item and its sub menu items
:param tkinter.Menu tools_menu: tools menu
:return: nothing
"""
menu = tk.Menu(tools_menu)
self.create_random_menu(menu)
@ -352,8 +298,6 @@ class Menubar(tk.Menu):
def draw_tools_menu(self):
"""
Create tools menu
:return: nothing
"""
menu = tk.Menu(self)
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):
"""
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")
menu = tk.Menu(widget_menu)
@ -412,9 +353,6 @@ class Menubar(tk.Menu):
def create_adjacency_menu(self, widget_menu: tk.Menu):
"""
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.add_command(label="OSPFv2", state=tk.DISABLED)
@ -426,8 +364,6 @@ class Menubar(tk.Menu):
def draw_widgets_menu(self):
"""
Create widget menu
:return: nothing
"""
menu = tk.Menu(self)
self.create_observer_widgets_menu(menu)
@ -443,8 +379,6 @@ class Menubar(tk.Menu):
def draw_session_menu(self):
"""
Create session menu
:return: nothing
"""
menu = tk.Menu(self)
menu.add_command(
@ -461,8 +395,6 @@ class Menubar(tk.Menu):
def draw_help_menu(self):
"""
Create help menu
:return: nothing
"""
menu = tk.Menu(self)
menu.add_command(

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,7 @@
import logging
import tkinter as tk
from functools import partial
from pathlib import PosixPath
from tkinter import filedialog, font, ttk
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)
if file_path:
value.set(file_path)
@ -49,13 +50,13 @@ class FrameScroll(ttk.Frame):
self.frame.bind("<Configure>", self._configure_frame)
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()
if req_width != self.canvas.winfo_reqwidth():
self.canvas.configure(width=req_width)
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)
def clear(self):
@ -238,7 +239,7 @@ class Spinbox(ttk.Entry):
self.tk.call(self._w, "set", value)
def image_chooser(parent, path):
def image_chooser(parent: tk.Widget, path: PosixPath):
return filedialog.askopenfilename(
parent=parent,
initialdir=str(path),