From bc026bb69369c2dbb7ae733f44744fffeb99b251 Mon Sep 17 00:00:00 2001 From: Blake Harnden <32446120+bharnden@users.noreply.github.com> Date: Tue, 26 Nov 2019 11:32:48 -0800 Subject: [PATCH] initial work for mobility player dialog, added default sample1.xml to created gui directory, fixed issue with non modal dialogs --- coretk/coretk/appconfig.py | 4 + coretk/coretk/coreclient.py | 30 ++- coretk/coretk/dialogs/dialog.py | 2 +- coretk/coretk/dialogs/mobilityplayer.py | 61 +++++ coretk/coretk/linkinfo.py | 11 +- coretk/coretk/menuaction.py | 2 +- coretk/coretk/xmls/sample1.xml | 296 ++++++++++++++++++++++++ 7 files changed, 397 insertions(+), 9 deletions(-) create mode 100644 coretk/coretk/dialogs/mobilityplayer.py create mode 100644 coretk/coretk/xmls/sample1.xml diff --git a/coretk/coretk/appconfig.py b/coretk/coretk/appconfig.py index 2af1047c..74d52553 100644 --- a/coretk/coretk/appconfig.py +++ b/coretk/coretk/appconfig.py @@ -20,6 +20,7 @@ CONFIG_PATH = HOME_PATH.joinpath("gui.yaml") # local paths LOCAL_ICONS_PATH = Path(__file__).parent.joinpath("icons").absolute() LOCAL_BACKGROUND_PATH = Path(__file__).parent.joinpath("backgrounds").absolute() +LOCAL_XMLS_PATH = Path(__file__).parent.joinpath("xmls").absolute() # configuration data TERMINALS = [ @@ -59,6 +60,9 @@ def check_directory(): for background in LOCAL_BACKGROUND_PATH.glob("*"): new_background = BACKGROUNDS_PATH.joinpath(background.name) shutil.copy(background, new_background) + for xml_file in LOCAL_XMLS_PATH.glob("*"): + new_xml = XML_PATH.joinpath(xml_file.name) + shutil.copy(xml_file, new_xml) if "TERM" in os.environ: terminal = TERMINALS[0] diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index 71d6da1b..865baedc 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -5,6 +5,7 @@ import logging import os from core.api.grpc import client, core_pb2 +from coretk.dialogs.mobilityplayer import MobilityPlayerDialog from coretk.dialogs.sessions import SessionsDialog from coretk.interface import InterfaceManager from coretk.nodeutils import NodeDraw, NodeUtils @@ -74,6 +75,7 @@ class CoreClient: self.emane_config = None self.service_configs = {} self.file_configs = {} + self.mobility_players = {} def reset(self): # helpers @@ -91,6 +93,7 @@ class CoreClient: self.emane_config = None self.service_configs.clear() self.file_configs.clear() + self.mobility_players.clear() def set_observer(self, value): self.observer = value @@ -119,8 +122,33 @@ class CoreClient: if event.HasField("link_event"): self.app.canvas.wireless_draw.handle_link_event(event.link_event) elif event.HasField("session_event"): - if event.session_event.event <= core_pb2.SessionState.SHUTDOWN: + session_event = event.session_event + if session_event.event <= core_pb2.SessionState.SHUTDOWN: self.state = event.session_event.event + # mobility start + elif session_event.event == 7: + node_id = session_event.node_id + if node_id not in self.mobility_players: + canvas_node = self.canvas_nodes[node_id] + dialog = MobilityPlayerDialog(self.app, self.app, canvas_node) + dialog.show() + self.mobility_players[node_id] = dialog + # mobility stop + elif session_event.event == 8: + node_id = session_event.node_id + if node_id not in self.mobility_players: + canvas_node = self.canvas_nodes[node_id] + dialog = MobilityPlayerDialog(self.app, self.app, canvas_node) + dialog.show() + self.mobility_players[node_id] = dialog + # mobility pause + elif session_event.event == 9: + node_id = session_event.node_id + if node_id not in self.mobility_players: + canvas_node = self.canvas_nodes[node_id] + dialog = MobilityPlayerDialog(self.app, self.app, canvas_node) + dialog.show() + self.mobility_players[node_id] = dialog def handle_throughputs(self, event): interface_throughputs = event.interface_throughputs diff --git a/coretk/coretk/dialogs/dialog.py b/coretk/coretk/dialogs/dialog.py index 769fd176..29362960 100644 --- a/coretk/coretk/dialogs/dialog.py +++ b/coretk/coretk/dialogs/dialog.py @@ -29,4 +29,4 @@ class Dialog(tk.Toplevel): if self.modal: self.wait_visibility() self.grab_set() - self.wait_window() + self.wait_window() diff --git a/coretk/coretk/dialogs/mobilityplayer.py b/coretk/coretk/dialogs/mobilityplayer.py new file mode 100644 index 00000000..cac4caa7 --- /dev/null +++ b/coretk/coretk/dialogs/mobilityplayer.py @@ -0,0 +1,61 @@ +from tkinter import ttk + +from coretk.dialogs.dialog import Dialog + +PAD = 5 + + +class MobilityPlayerDialog(Dialog): + def __init__(self, master, app, canvas_node): + super().__init__( + master, app, f"{canvas_node.core_node.name} Mobility Player", modal=False + ) + self.play_button = None + self.pause_button = None + self.stop_button = None + self.draw() + + def draw(self): + self.top.columnconfigure(0, weight=1) + + label = ttk.Label(self.top, text="File Name") + label.grid(sticky="ew", pady=PAD) + + frame = ttk.Frame(self.top) + frame.grid(sticky="ew", pady=PAD) + frame.columnconfigure(0, weight=1) + progressbar = ttk.Progressbar(frame, mode="indeterminate") + progressbar.grid(row=0, column=0, sticky="ew", padx=PAD) + progressbar.start() + label = ttk.Label(frame, text="time") + label.grid(row=0, column=1) + + frame = ttk.Frame(self.top) + frame.grid(sticky="ew", pady=PAD) + self.play_button = ttk.Button(frame, text="Play", command=self.click_play) + self.play_button.grid(row=0, column=0, sticky="ew", padx=PAD) + self.pause_button = ttk.Button(frame, text="Pause", command=self.click_pause) + self.pause_button.grid(row=0, column=1, sticky="ew", padx=PAD) + self.stop_button = ttk.Button(frame, text="Stop", command=self.click_stop) + self.stop_button.grid(row=0, column=2, sticky="ew", padx=PAD) + checkbutton = ttk.Checkbutton(frame, text="Loop?") + checkbutton.grid(row=0, column=3, padx=PAD) + label = ttk.Label(frame, text="rate 50 ms") + label.grid(row=0, column=4) + + def clear_buttons(self): + self.play_button.state(["!pressed"]) + self.pause_button.state(["!pressed"]) + self.stop_button.state(["!pressed"]) + + def click_play(self): + self.clear_buttons() + self.play_button.state(["pressed"]) + + def click_pause(self): + self.clear_buttons() + self.pause_button.state(["pressed"]) + + def click_stop(self): + self.clear_buttons() + self.stop_button.state(["pressed"]) diff --git a/coretk/coretk/linkinfo.py b/coretk/coretk/linkinfo.py index 9004afe8..c78fe7e4 100644 --- a/coretk/coretk/linkinfo.py +++ b/coretk/coretk/linkinfo.py @@ -2,10 +2,10 @@ Link information, such as IPv4, IPv6 and throughput drawn in the canvas """ import logging -import math import tkinter as tk +from tkinter import font -TEXT_DISTANCE = 0.33 +TEXT_DISTANCE = 0.30 class LinkInfo: @@ -21,20 +21,19 @@ class LinkInfo: self.link = link self.id1 = None self.id2 = None + self.font = font.Font(size=8) self.draw_labels() def get_coordinates(self): x1, y1, x2, y2 = self.canvas.coords(self.edge.id) v1 = x2 - x1 v2 = y2 - y1 - d = math.sqrt(v1 ** 2 + v2 ** 2) ux = TEXT_DISTANCE * v1 uy = TEXT_DISTANCE * v2 x1 = x1 + ux y1 = y1 + uy x2 = x2 - ux y2 = y2 - uy - logging.info("line distance: %s", d) return x1, y1, x2, y2 def draw_labels(self): @@ -52,10 +51,10 @@ class LinkInfo: f"{self.link.interface_two.ip6}/{self.link.interface_two.ip6mask}\n" ) self.id1 = self.canvas.create_text( - x1, y1, text=label_one, justify=tk.CENTER, tags="linkinfo" + x1, y1, text=label_one, justify=tk.CENTER, font=self.font, tags="linkinfo" ) self.id2 = self.canvas.create_text( - x2, y2, text=label_two, justify=tk.CENTER, tags="linkinfo" + x2, y2, text=label_two, justify=tk.CENTER, font=self.font, tags="linkinfo" ) def recalculate_info(self): diff --git a/coretk/coretk/menuaction.py b/coretk/coretk/menuaction.py index b47c6ef2..89386162 100644 --- a/coretk/coretk/menuaction.py +++ b/coretk/coretk/menuaction.py @@ -76,7 +76,7 @@ class MenuAction: file_path = filedialog.askopenfilename( initialdir=str(XML_PATH), title="Open", - filetypes=(("EmulationScript XML File", "*.xml"), ("All Files", "*")), + filetypes=(("XML Files", "*.xml"), ("All Files", "*")), ) if file_path: logging.info("opening xml: %s", file_path) diff --git a/coretk/coretk/xmls/sample1.xml b/coretk/coretk/xmls/sample1.xml new file mode 100644 index 00000000..cfa5a99a --- /dev/null +++ b/coretk/coretk/xmls/sample1.xml @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /usr/local/etc/quagga + /var/run/quagga + + + sh quaggaboot.sh zebra + + + pidof zebra + + + killall zebra + + + interface eth0 + ip address 10.0.0.5/32 + ipv6 address a::3/128 + ipv6 ospf6 instance-id 65 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 6 + ipv6 ospf6 retransmit-interval 5 + ipv6 ospf6 network manet-designated-router + ipv6 ospf6 diffhellos + ipv6 ospf6 adjacencyconnectivity uniconnected + ipv6 ospf6 lsafullness mincostlsa +! +interface eth1 + ip address 10.0.6.2/24 + !ip ospf hello-interval 2 + !ip ospf dead-interval 6 + !ip ospf retransmit-interval 5 + !ip ospf network point-to-point + ipv6 address a:6::2/64 +! +router ospf + router-id 10.0.0.5 + network 10.0.0.5/32 area 0 + network 10.0.6.0/24 area 0 + redistribute connected metric-type 1 + redistribute ospf6 metric-type 1 +! +router ospf6 + router-id 10.0.0.5 + interface eth0 area 0.0.0.0 + redistribute connected + redistribute ospf +! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +