merged latest from coretk and started work on emane configurations
This commit is contained in:
commit
cdb4ed571b
34 changed files with 1330 additions and 740 deletions
|
@ -1,9 +1,8 @@
|
||||||
import logging
|
import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
|
||||||
import coretk.appcache as appcache
|
from coretk import appdirs
|
||||||
import coretk.images as images
|
from coretk.coreclient import CoreClient
|
||||||
from coretk.coregrpc import CoreGrpc
|
|
||||||
from coretk.coremenubar import CoreMenubar
|
from coretk.coremenubar import CoreMenubar
|
||||||
from coretk.coretoolbar import CoreToolbar
|
from coretk.coretoolbar import CoreToolbar
|
||||||
from coretk.graph import CanvasGraph
|
from coretk.graph import CanvasGraph
|
||||||
|
@ -14,43 +13,42 @@ from coretk.menuaction import MenuAction
|
||||||
class Application(tk.Frame):
|
class Application(tk.Frame):
|
||||||
def __init__(self, master=None):
|
def __init__(self, master=None):
|
||||||
super().__init__(master)
|
super().__init__(master)
|
||||||
appcache.cache_variable(self)
|
Images.load_all()
|
||||||
self.load_images()
|
|
||||||
self.setup_app()
|
|
||||||
self.menubar = None
|
self.menubar = None
|
||||||
self.core_menu = None
|
self.core_menu = None
|
||||||
self.canvas = None
|
self.canvas = None
|
||||||
self.core_editbar = None
|
self.core_editbar = None
|
||||||
self.core_grpc = None
|
self.is_open_xml = False
|
||||||
|
self.size_and_scale = None
|
||||||
self.create_menu()
|
self.set_wallpaper = None
|
||||||
self.create_widgets()
|
self.wallpaper_id = None
|
||||||
|
self.current_wallpaper = None
|
||||||
|
self.radiovar = tk.IntVar(value=1)
|
||||||
|
self.show_grid_var = tk.IntVar(value=1)
|
||||||
|
self.adjust_to_dim_var = tk.IntVar(value=0)
|
||||||
|
self.core = CoreClient(self)
|
||||||
|
self.setup_app()
|
||||||
|
self.draw_menu()
|
||||||
|
self.draw_toolbar()
|
||||||
self.draw_canvas()
|
self.draw_canvas()
|
||||||
self.start_grpc()
|
self.core.set_up()
|
||||||
# self.try_make_table()
|
|
||||||
|
|
||||||
def load_images(self):
|
|
||||||
"""
|
|
||||||
Load core images
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
images.load_core_images(Images)
|
|
||||||
|
|
||||||
def setup_app(self):
|
def setup_app(self):
|
||||||
self.master.title("CORE")
|
self.master.title("CORE")
|
||||||
self.master.geometry("1000x800")
|
self.master.geometry("1000x800")
|
||||||
|
self.master.protocol("WM_DELETE_WINDOW", self.on_closing)
|
||||||
image = Images.get(ImageEnum.CORE)
|
image = Images.get(ImageEnum.CORE)
|
||||||
self.master.tk.call("wm", "iconphoto", self.master._w, image)
|
self.master.tk.call("wm", "iconphoto", self.master._w, image)
|
||||||
self.pack(fill=tk.BOTH, expand=True)
|
self.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
def create_menu(self):
|
def draw_menu(self):
|
||||||
self.master.option_add("*tearOff", tk.FALSE)
|
self.master.option_add("*tearOff", tk.FALSE)
|
||||||
self.menubar = tk.Menu(self.master)
|
self.menubar = tk.Menu(self.master)
|
||||||
self.core_menu = CoreMenubar(self, self.master, self.menubar)
|
self.core_menu = CoreMenubar(self, self.master, self.menubar)
|
||||||
self.core_menu.create_core_menubar()
|
self.core_menu.create_core_menubar()
|
||||||
self.master.config(menu=self.menubar)
|
self.master.config(menu=self.menubar)
|
||||||
|
|
||||||
def create_widgets(self):
|
def draw_toolbar(self):
|
||||||
edit_frame = tk.Frame(self)
|
edit_frame = tk.Frame(self)
|
||||||
edit_frame.pack(side=tk.LEFT, fill=tk.Y, ipadx=2, ipady=2)
|
edit_frame.pack(side=tk.LEFT, fill=tk.Y, ipadx=2, ipady=2)
|
||||||
self.core_editbar = CoreToolbar(self, edit_frame, self.menubar)
|
self.core_editbar = CoreToolbar(self, edit_frame, self.menubar)
|
||||||
|
@ -58,10 +56,7 @@ class Application(tk.Frame):
|
||||||
|
|
||||||
def draw_canvas(self):
|
def draw_canvas(self):
|
||||||
self.canvas = CanvasGraph(
|
self.canvas = CanvasGraph(
|
||||||
master=self,
|
self, self.core, background="#cccccc", scrollregion=(0, 0, 1200, 1000)
|
||||||
grpc=self.core_grpc,
|
|
||||||
background="#cccccc",
|
|
||||||
scrollregion=(0, 0, 1200, 1000),
|
|
||||||
)
|
)
|
||||||
self.canvas.pack(fill=tk.BOTH, expand=True)
|
self.canvas.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
@ -85,39 +80,13 @@ class Application(tk.Frame):
|
||||||
b = tk.Button(status_bar, text="Button 3")
|
b = tk.Button(status_bar, text="Button 3")
|
||||||
b.pack(side=tk.LEFT, padx=1)
|
b.pack(side=tk.LEFT, padx=1)
|
||||||
|
|
||||||
def start_grpc(self):
|
|
||||||
"""
|
|
||||||
Conect client to grpc, query sessions and prompt use to choose an existing session if there exist any
|
|
||||||
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
self.master.update()
|
|
||||||
self.core_grpc = CoreGrpc(self)
|
|
||||||
self.core_grpc.set_up()
|
|
||||||
self.canvas.core_grpc = self.core_grpc
|
|
||||||
self.canvas.grpc_manager.core_grpc = self.core_grpc
|
|
||||||
self.canvas.grpc_manager.update_preexisting_ids()
|
|
||||||
self.canvas.draw_existing_component()
|
|
||||||
|
|
||||||
self.canvas.grpc_manager.wlanconfig_management.load_wlan_configurations(
|
|
||||||
self.core_grpc
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_closing(self):
|
def on_closing(self):
|
||||||
menu_action = MenuAction(self, self.master)
|
menu_action = MenuAction(self, self.master)
|
||||||
menu_action.on_quit()
|
menu_action.on_quit()
|
||||||
# self.quit()
|
|
||||||
|
|
||||||
def try_make_table(self):
|
|
||||||
f = tk.Frame(self.master)
|
|
||||||
for i in range(3):
|
|
||||||
e = tk.Entry(f)
|
|
||||||
e.grid(row=0, column=1, stick="nsew")
|
|
||||||
f.pack(side=tk.TOP)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
appdirs.check_directory()
|
||||||
app = Application()
|
app = Application()
|
||||||
app.master.protocol("WM_DELETE_WINDOW", app.on_closing)
|
|
||||||
app.mainloop()
|
app.mainloop()
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
"""
|
|
||||||
stores some information helpful for setting starting values for some tables
|
|
||||||
like size and scale, set wallpaper, etc
|
|
||||||
"""
|
|
||||||
import tkinter as tk
|
|
||||||
|
|
||||||
|
|
||||||
def cache_variable(application):
|
|
||||||
# for menubar
|
|
||||||
application.is_open_xml = False
|
|
||||||
|
|
||||||
application.size_and_scale = None
|
|
||||||
application.set_wallpaper = None
|
|
||||||
|
|
||||||
# set wallpaper variables
|
|
||||||
|
|
||||||
# canvas id of the wallpaper
|
|
||||||
application.wallpaper_id = None
|
|
||||||
|
|
||||||
# current image for wallpaper
|
|
||||||
application.current_wallpaper = None
|
|
||||||
|
|
||||||
# wallpaper option
|
|
||||||
application.radiovar = tk.IntVar()
|
|
||||||
application.radiovar.set(1)
|
|
||||||
|
|
||||||
# show grid option
|
|
||||||
application.show_grid_var = tk.IntVar()
|
|
||||||
application.show_grid_var.set(1)
|
|
||||||
|
|
||||||
# adjust canvas to image dimension variable
|
|
||||||
application.adjust_to_dim_var = tk.IntVar()
|
|
||||||
application.adjust_to_dim_var.set(0)
|
|
39
coretk/coretk/appdirs.py
Normal file
39
coretk/coretk/appdirs.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import logging
|
||||||
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# gui home paths
|
||||||
|
HOME_PATH = Path.home().joinpath(".coretk")
|
||||||
|
BACKGROUNDS_PATH = HOME_PATH.joinpath("backgrounds")
|
||||||
|
CUSTOM_EMANE_PATH = HOME_PATH.joinpath("custom_emane")
|
||||||
|
CUSTOM_SERVICE_PATH = HOME_PATH.joinpath("custom_services")
|
||||||
|
ICONS_PATH = HOME_PATH.joinpath("icons")
|
||||||
|
MOBILITY_PATH = HOME_PATH.joinpath("mobility")
|
||||||
|
XML_PATH = HOME_PATH.joinpath("xml")
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
def check_directory():
|
||||||
|
if HOME_PATH.exists():
|
||||||
|
logging.info("~/.coretk exists")
|
||||||
|
return
|
||||||
|
logging.info("creating ~/.coretk")
|
||||||
|
HOME_PATH.mkdir()
|
||||||
|
BACKGROUNDS_PATH.mkdir()
|
||||||
|
CUSTOM_EMANE_PATH.mkdir()
|
||||||
|
CUSTOM_SERVICE_PATH.mkdir()
|
||||||
|
ICONS_PATH.mkdir()
|
||||||
|
MOBILITY_PATH.mkdir()
|
||||||
|
XML_PATH.mkdir()
|
||||||
|
for image in LOCAL_ICONS_PATH.glob("*"):
|
||||||
|
new_image = ICONS_PATH.joinpath(image.name)
|
||||||
|
shutil.copy(image, new_image)
|
||||||
|
for background in LOCAL_BACKGROUND_PATH.glob("*"):
|
||||||
|
new_background = BACKGROUNDS_PATH.joinpath(background.name)
|
||||||
|
shutil.copy(background, new_background)
|
||||||
|
with CONFIG_PATH.open("w") as f:
|
||||||
|
f.write("# gui config")
|
Before Width: | Height: | Size: 312 KiB After Width: | Height: | Size: 312 KiB |
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 196 KiB |
|
@ -1,13 +1,10 @@
|
||||||
"""
|
"""
|
||||||
canvas graph action
|
canvas graph action
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# import tkinter as tk
|
|
||||||
|
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
from coretk.dialogs.emaneconfig import EmaneConfiguration
|
from coretk.dialogs.emaneconfig import EmaneConfiguration
|
||||||
from coretk.nodeconfigtable import NodeConfig
|
from coretk.dialogs.nodeconfig import NodeConfigDialog
|
||||||
from coretk.wlanconfiguration import WlanConfiguration
|
from coretk.dialogs.wlanconfig import WlanConfiguration
|
||||||
|
|
||||||
# TODO, finish classifying node types
|
# TODO, finish classifying node types
|
||||||
NODE_TO_TYPE = {
|
NODE_TO_TYPE = {
|
||||||
|
@ -20,7 +17,6 @@ NODE_TO_TYPE = {
|
||||||
class CanvasAction:
|
class CanvasAction:
|
||||||
def __init__(self, master, canvas):
|
def __init__(self, master, canvas):
|
||||||
self.master = master
|
self.master = master
|
||||||
|
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.node_to_show_config = None
|
self.node_to_show_config = None
|
||||||
|
|
||||||
|
@ -35,19 +31,19 @@ class CanvasAction:
|
||||||
self.display_emane_configuration()
|
self.display_emane_configuration()
|
||||||
|
|
||||||
def display_node_configuration(self):
|
def display_node_configuration(self):
|
||||||
NodeConfig(self.canvas, self.node_to_show_config)
|
dialog = NodeConfigDialog(self.master, self.master, self.node_to_show_config)
|
||||||
|
dialog.show()
|
||||||
self.node_to_show_config = None
|
self.node_to_show_config = None
|
||||||
|
|
||||||
def display_wlan_configuration(self, canvas_node):
|
def display_wlan_configuration(self, canvas_node):
|
||||||
# print(self.canvas.grpc_manager.wlanconfig_management.configurations)
|
wlan_config = self.canvas.core.wlanconfig_management.configurations[
|
||||||
wlan_config = self.canvas.grpc_manager.wlanconfig_management.configurations[
|
|
||||||
canvas_node.core_id
|
canvas_node.core_id
|
||||||
]
|
]
|
||||||
WlanConfiguration(self.canvas, self.node_to_show_config, wlan_config)
|
WlanConfiguration(self.canvas, self.node_to_show_config, wlan_config)
|
||||||
self.node_to_show_config = None
|
self.node_to_show_config = None
|
||||||
|
|
||||||
def display_emane_configuration(self):
|
def display_emane_configuration(self):
|
||||||
app = self.canvas.core_grpc.app
|
app = self.canvas.core.app
|
||||||
dialog = EmaneConfiguration(self.master, app, self.node_to_show_config)
|
dialog = EmaneConfiguration(self.master, app, self.node_to_show_config)
|
||||||
print(dialog)
|
print(dialog)
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
635
coretk/coretk/coreclient.py
Normal file
635
coretk/coretk/coreclient.py
Normal file
|
@ -0,0 +1,635 @@
|
||||||
|
"""
|
||||||
|
Incorporate grpc into python tkinter GUI
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from core.api.grpc import client, core_pb2
|
||||||
|
from coretk.coretocanvas import CoreToCanvasMapping
|
||||||
|
from coretk.dialogs.sessions import SessionsDialog
|
||||||
|
from coretk.interface import Interface, InterfaceManager
|
||||||
|
from coretk.mobilitynodeconfig import MobilityNodeConfig
|
||||||
|
from coretk.wlannodeconfig import WlanNodeConfig
|
||||||
|
|
||||||
|
link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"]
|
||||||
|
network_layer_nodes = ["router", "host", "PC", "mdr", "prouter", "OVS"]
|
||||||
|
|
||||||
|
|
||||||
|
class Node:
|
||||||
|
def __init__(self, session_id, node_id, node_type, model, x, y, name):
|
||||||
|
"""
|
||||||
|
Create an instance of a node
|
||||||
|
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int node_id: node id
|
||||||
|
:param core_pb2.NodeType node_type: node type
|
||||||
|
:param int x: x coordinate
|
||||||
|
:param int y: coordinate
|
||||||
|
:param str name: node name
|
||||||
|
"""
|
||||||
|
self.session_id = session_id
|
||||||
|
self.node_id = node_id
|
||||||
|
self.type = node_type
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.model = model
|
||||||
|
self.name = name
|
||||||
|
self.interfaces = []
|
||||||
|
|
||||||
|
|
||||||
|
class Edge:
|
||||||
|
def __init__(self, session_id, node_id_1, node_type_1, node_id_2, node_type_2):
|
||||||
|
"""
|
||||||
|
Create an instance of an edge
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int node_id_1: node 1 id
|
||||||
|
:param int node_type_1: node 1 type
|
||||||
|
:param core_pb2.NodeType node_id_2: node 2 id
|
||||||
|
:param core_pb2.NodeType node_type_2: node 2 type
|
||||||
|
"""
|
||||||
|
self.session_id = session_id
|
||||||
|
self.id1 = node_id_1
|
||||||
|
self.id2 = node_id_2
|
||||||
|
self.type1 = node_type_1
|
||||||
|
self.type2 = node_type_2
|
||||||
|
self.interface_1 = None
|
||||||
|
self.interface_2 = None
|
||||||
|
|
||||||
|
|
||||||
|
class CoreClient:
|
||||||
|
def __init__(self, app):
|
||||||
|
"""
|
||||||
|
Create a CoreGrpc instance
|
||||||
|
"""
|
||||||
|
self.client = client.CoreGrpcClient()
|
||||||
|
self.session_id = None
|
||||||
|
self.node_ids = []
|
||||||
|
self.app = app
|
||||||
|
self.master = app.master
|
||||||
|
self.interface_helper = None
|
||||||
|
|
||||||
|
# data for managing the current session
|
||||||
|
self.nodes = {}
|
||||||
|
self.edges = {}
|
||||||
|
self.hooks = {}
|
||||||
|
self.id = 1
|
||||||
|
self.reusable = []
|
||||||
|
self.preexisting = set()
|
||||||
|
self.interfaces_manager = InterfaceManager()
|
||||||
|
self.core_mapping = CoreToCanvasMapping()
|
||||||
|
self.wlanconfig_management = WlanNodeConfig()
|
||||||
|
self.mobilityconfig_management = MobilityNodeConfig()
|
||||||
|
|
||||||
|
def handle_events(self, event):
|
||||||
|
logging.info("event: %s", event)
|
||||||
|
if event.link_event is not None:
|
||||||
|
self.app.canvas.wireless_draw.hangle_link_event(event.link_event)
|
||||||
|
|
||||||
|
def handle_throughputs(self, event):
|
||||||
|
interface_throughputs = event.interface_throughputs
|
||||||
|
for i in interface_throughputs:
|
||||||
|
print("")
|
||||||
|
return
|
||||||
|
throughputs_belong_to_session = []
|
||||||
|
for if_tp in interface_throughputs:
|
||||||
|
if if_tp.node_id in self.node_ids:
|
||||||
|
throughputs_belong_to_session.append(if_tp)
|
||||||
|
self.throughput_draw.process_grpc_throughput_event(
|
||||||
|
throughputs_belong_to_session
|
||||||
|
)
|
||||||
|
|
||||||
|
def join_session(self, session_id):
|
||||||
|
# update session and title
|
||||||
|
self.session_id = session_id
|
||||||
|
self.master.title(f"CORE Session({self.session_id})")
|
||||||
|
|
||||||
|
# clear session data
|
||||||
|
self.reusable.clear()
|
||||||
|
self.preexisting.clear()
|
||||||
|
self.nodes.clear()
|
||||||
|
self.edges.clear()
|
||||||
|
self.hooks.clear()
|
||||||
|
|
||||||
|
# get session data
|
||||||
|
response = self.client.get_session(self.session_id)
|
||||||
|
logging.info("joining session(%s): %s", self.session_id, response)
|
||||||
|
session = response.session
|
||||||
|
self.client.events(self.session_id, self.handle_events)
|
||||||
|
|
||||||
|
# get hooks
|
||||||
|
response = self.client.get_hooks(self.session_id)
|
||||||
|
logging.info("joined session hooks: %s", response)
|
||||||
|
for hook in response.hooks:
|
||||||
|
self.hooks[hook.file] = hook
|
||||||
|
|
||||||
|
# get wlan configs
|
||||||
|
for node in session.nodes:
|
||||||
|
if node.type == core_pb2.NodeType.WIRELESS_LAN:
|
||||||
|
response = self.client.get_wlan_config(self.session_id, node.id)
|
||||||
|
node_config = response.config
|
||||||
|
config = {x: node_config[x].value for x in node_config}
|
||||||
|
self.wlanconfig_management.configurations[node.id] = config
|
||||||
|
|
||||||
|
# get mobility configs
|
||||||
|
response = self.client.get_mobility_configs(self.session_id)
|
||||||
|
for node_id in response.config:
|
||||||
|
node_config = response.config[node_id].config
|
||||||
|
config = {x: node_config[x].value for x in node_config}
|
||||||
|
self.mobilityconfig_management.configurations[node_id] = config
|
||||||
|
|
||||||
|
# determine next node id and reusable nodes
|
||||||
|
max_id = 1
|
||||||
|
for node in session.nodes:
|
||||||
|
if node.id > max_id:
|
||||||
|
max_id = node.id
|
||||||
|
self.preexisting.add(node.id)
|
||||||
|
self.id = max_id
|
||||||
|
for i in range(1, self.id):
|
||||||
|
if i not in self.preexisting:
|
||||||
|
self.reusable.append(i)
|
||||||
|
|
||||||
|
# draw session
|
||||||
|
self.app.canvas.canvas_reset_and_redraw(session)
|
||||||
|
|
||||||
|
def create_new_session(self):
|
||||||
|
"""
|
||||||
|
Create a new session
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
response = self.client.create_session()
|
||||||
|
logging.info("created session: %s", response)
|
||||||
|
self.join_session(response.session_id)
|
||||||
|
|
||||||
|
def delete_session(self, custom_sid=None):
|
||||||
|
if custom_sid is None:
|
||||||
|
sid = self.session_id
|
||||||
|
else:
|
||||||
|
sid = custom_sid
|
||||||
|
response = self.client.delete_session(sid)
|
||||||
|
logging.info("Deleted session result: %s", response)
|
||||||
|
|
||||||
|
def shutdown_session(self, custom_sid=None):
|
||||||
|
if custom_sid is None:
|
||||||
|
sid = self.session_id
|
||||||
|
else:
|
||||||
|
sid = custom_sid
|
||||||
|
s = self.client.get_session(sid).session
|
||||||
|
# delete links and nodes from running session
|
||||||
|
if s.state == core_pb2.SessionState.RUNTIME:
|
||||||
|
self.set_session_state("datacollect", sid)
|
||||||
|
self.delete_links(sid)
|
||||||
|
self.delete_nodes(sid)
|
||||||
|
self.delete_session(sid)
|
||||||
|
|
||||||
|
def set_up(self):
|
||||||
|
"""
|
||||||
|
Query sessions, if there exist any, prompt whether to join one
|
||||||
|
|
||||||
|
:return: existing sessions
|
||||||
|
"""
|
||||||
|
self.client.connect()
|
||||||
|
response = self.client.get_sessions()
|
||||||
|
|
||||||
|
# if there are no sessions, create a new session, else join a session
|
||||||
|
sessions = response.sessions
|
||||||
|
if len(sessions) == 0:
|
||||||
|
self.create_new_session()
|
||||||
|
else:
|
||||||
|
dialog = SessionsDialog(self.app, self.app)
|
||||||
|
dialog.show()
|
||||||
|
|
||||||
|
def get_session_state(self):
|
||||||
|
response = self.client.get_session(self.session_id)
|
||||||
|
# logging.info("get session: %s", response)
|
||||||
|
return response.session.state
|
||||||
|
|
||||||
|
def set_session_state(self, state, custom_session_id=None):
|
||||||
|
"""
|
||||||
|
Set session state
|
||||||
|
|
||||||
|
:param str state: session state to set
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if custom_session_id is None:
|
||||||
|
sid = self.session_id
|
||||||
|
else:
|
||||||
|
sid = custom_session_id
|
||||||
|
|
||||||
|
response = None
|
||||||
|
if state == "configuration":
|
||||||
|
response = self.client.set_session_state(
|
||||||
|
sid, core_pb2.SessionState.CONFIGURATION
|
||||||
|
)
|
||||||
|
elif state == "instantiation":
|
||||||
|
response = self.client.set_session_state(
|
||||||
|
sid, core_pb2.SessionState.INSTANTIATION
|
||||||
|
)
|
||||||
|
elif state == "datacollect":
|
||||||
|
response = self.client.set_session_state(
|
||||||
|
sid, core_pb2.SessionState.DATACOLLECT
|
||||||
|
)
|
||||||
|
elif state == "shutdown":
|
||||||
|
response = self.client.set_session_state(
|
||||||
|
sid, core_pb2.SessionState.SHUTDOWN
|
||||||
|
)
|
||||||
|
elif state == "runtime":
|
||||||
|
response = self.client.set_session_state(sid, core_pb2.SessionState.RUNTIME)
|
||||||
|
elif state == "definition":
|
||||||
|
response = self.client.set_session_state(
|
||||||
|
sid, core_pb2.SessionState.DEFINITION
|
||||||
|
)
|
||||||
|
elif state == "none":
|
||||||
|
response = self.client.set_session_state(sid, core_pb2.SessionState.NONE)
|
||||||
|
else:
|
||||||
|
logging.error("coregrpc.py: set_session_state: INVALID STATE")
|
||||||
|
|
||||||
|
logging.info("set session state: %s", response)
|
||||||
|
|
||||||
|
def edit_node(self, node_id, x, y):
|
||||||
|
position = core_pb2.Position(x=x, y=y)
|
||||||
|
response = self.client.edit_node(self.session_id, node_id, position)
|
||||||
|
logging.info("updated node id %s: %s", node_id, response)
|
||||||
|
|
||||||
|
def delete_nodes(self, delete_session=None):
|
||||||
|
if delete_session is None:
|
||||||
|
sid = self.session_id
|
||||||
|
else:
|
||||||
|
sid = delete_session
|
||||||
|
for node in self.client.get_session(sid).session.nodes:
|
||||||
|
response = self.client.delete_node(self.session_id, node.id)
|
||||||
|
logging.info("delete nodes %s", response)
|
||||||
|
|
||||||
|
def delete_links(self, delete_session=None):
|
||||||
|
# sid = None
|
||||||
|
if delete_session is None:
|
||||||
|
sid = self.session_id
|
||||||
|
else:
|
||||||
|
sid = delete_session
|
||||||
|
|
||||||
|
for link in self.client.get_session(sid).session.links:
|
||||||
|
response = self.client.delete_link(
|
||||||
|
self.session_id,
|
||||||
|
link.node_one_id,
|
||||||
|
link.node_two_id,
|
||||||
|
link.interface_one.id,
|
||||||
|
link.interface_two.id,
|
||||||
|
)
|
||||||
|
logging.info("delete links %s", response)
|
||||||
|
|
||||||
|
# TODO add location, hooks, emane_config, etc...
|
||||||
|
def start_session(
|
||||||
|
self,
|
||||||
|
nodes,
|
||||||
|
links,
|
||||||
|
location=None,
|
||||||
|
hooks=None,
|
||||||
|
emane_config=None,
|
||||||
|
emane_model_configs=None,
|
||||||
|
wlan_configs=None,
|
||||||
|
mobility_configs=None,
|
||||||
|
):
|
||||||
|
response = self.client.start_session(
|
||||||
|
self.session_id,
|
||||||
|
nodes,
|
||||||
|
links,
|
||||||
|
hooks=list(self.hooks.values()),
|
||||||
|
wlan_configs=wlan_configs,
|
||||||
|
)
|
||||||
|
logging.debug("Start session %s, result: %s", self.session_id, response.result)
|
||||||
|
|
||||||
|
def stop_session(self):
|
||||||
|
response = self.client.stop_session(session_id=self.session_id)
|
||||||
|
logging.debug("coregrpc.py Stop session, result: %s", response.result)
|
||||||
|
|
||||||
|
# TODO no need, might get rid of this
|
||||||
|
def add_link(self, id1, id2, type1, type2, edge):
|
||||||
|
"""
|
||||||
|
Grpc client request add link
|
||||||
|
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int id1: node 1 core id
|
||||||
|
:param core_pb2.NodeType type1: node 1 core node type
|
||||||
|
:param int id2: node 2 core id
|
||||||
|
:param core_pb2.NodeType type2: node 2 core node type
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if1 = self.create_interface(type1, edge.interface_1)
|
||||||
|
if2 = self.create_interface(type2, edge.interface_2)
|
||||||
|
response = self.client.add_link(self.session_id, id1, id2, if1, if2)
|
||||||
|
logging.info("created link: %s", response)
|
||||||
|
|
||||||
|
def launch_terminal(self, node_id):
|
||||||
|
response = self.client.get_node_terminal(self.session_id, node_id)
|
||||||
|
logging.info("get terminal %s", response.terminal)
|
||||||
|
os.system("xterm -e %s &" % response.terminal)
|
||||||
|
|
||||||
|
def save_xml(self, file_path):
|
||||||
|
"""
|
||||||
|
Save core session as to an xml file
|
||||||
|
|
||||||
|
:param str file_path: file path that user pick
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
response = self.client.save_xml(self.session_id, file_path)
|
||||||
|
logging.info("coregrpc.py save xml %s", response)
|
||||||
|
self.client.events(self.session_id, self.handle_events)
|
||||||
|
|
||||||
|
def open_xml(self, file_path):
|
||||||
|
"""
|
||||||
|
Open core xml
|
||||||
|
|
||||||
|
:param str file_path: file to open
|
||||||
|
:return: session id
|
||||||
|
"""
|
||||||
|
response = self.client.open_xml(file_path)
|
||||||
|
logging.debug("open xml: %s", response)
|
||||||
|
self.join_session(response.session_id)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
"""
|
||||||
|
Clean ups when done using grpc
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
logging.debug("Close grpc")
|
||||||
|
self.client.close()
|
||||||
|
|
||||||
|
def peek_id(self):
|
||||||
|
"""
|
||||||
|
Peek the next id to be used
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if len(self.reusable) == 0:
|
||||||
|
return self.id
|
||||||
|
else:
|
||||||
|
return self.reusable[0]
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
"""
|
||||||
|
Get the next node id as well as update id status and reusable ids
|
||||||
|
|
||||||
|
:rtype: int
|
||||||
|
:return: the next id to be used
|
||||||
|
"""
|
||||||
|
if len(self.reusable) == 0:
|
||||||
|
new_id = self.id
|
||||||
|
self.id = self.id + 1
|
||||||
|
return new_id
|
||||||
|
else:
|
||||||
|
return self.reusable.pop(0)
|
||||||
|
|
||||||
|
def add_node(self, node_type, model, x, y, name, node_id):
|
||||||
|
position = core_pb2.Position(x=x, y=y)
|
||||||
|
node = core_pb2.Node(id=node_id, type=node_type, position=position, model=model)
|
||||||
|
self.node_ids.append(node_id)
|
||||||
|
response = self.client.add_node(self.session_id, node)
|
||||||
|
logging.info("created node: %s", response)
|
||||||
|
if node_type == core_pb2.NodeType.WIRELESS_LAN:
|
||||||
|
d = OrderedDict()
|
||||||
|
d["basic_range"] = "275"
|
||||||
|
d["bandwidth"] = "54000000"
|
||||||
|
d["jitter"] = "0"
|
||||||
|
d["delay"] = "20000"
|
||||||
|
d["error"] = "0"
|
||||||
|
r = self.client.set_wlan_config(self.session_id, node_id, d)
|
||||||
|
logging.debug("set wlan config %s", r)
|
||||||
|
return response.node_id
|
||||||
|
|
||||||
|
def add_graph_node(self, session_id, canvas_id, x, y, name):
|
||||||
|
"""
|
||||||
|
Add node, with information filled in, to grpc manager
|
||||||
|
|
||||||
|
:param int session_id: session id
|
||||||
|
:param int canvas_id: node's canvas id
|
||||||
|
:param int x: x coord
|
||||||
|
:param int y: y coord
|
||||||
|
:param str name: node type
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
node_type = None
|
||||||
|
node_model = None
|
||||||
|
if name in link_layer_nodes:
|
||||||
|
if name == "switch":
|
||||||
|
node_type = core_pb2.NodeType.SWITCH
|
||||||
|
elif name == "hub":
|
||||||
|
node_type = core_pb2.NodeType.HUB
|
||||||
|
elif name == "wlan":
|
||||||
|
node_type = core_pb2.NodeType.WIRELESS_LAN
|
||||||
|
elif name == "rj45":
|
||||||
|
node_type = core_pb2.NodeType.RJ45
|
||||||
|
elif name == "tunnel":
|
||||||
|
node_type = core_pb2.NodeType.TUNNEL
|
||||||
|
elif name in network_layer_nodes:
|
||||||
|
node_type = core_pb2.NodeType.DEFAULT
|
||||||
|
node_model = name
|
||||||
|
else:
|
||||||
|
logging.error("grpcmanagemeny.py INVALID node name")
|
||||||
|
nid = self.get_id()
|
||||||
|
create_node = Node(session_id, nid, node_type, node_model, x, y, name)
|
||||||
|
|
||||||
|
# set default configuration for wireless node
|
||||||
|
self.wlanconfig_management.set_default_config(node_type, nid)
|
||||||
|
|
||||||
|
self.mobilityconfig_management.set_default_configuration(node_type, nid)
|
||||||
|
|
||||||
|
self.nodes[canvas_id] = create_node
|
||||||
|
self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id)
|
||||||
|
# self.core_id_to_canvas_id[nid] = canvas_id
|
||||||
|
logging.debug(
|
||||||
|
"Adding node to GrpcManager.. Session id: %s, Coords: (%s, %s), Name: %s",
|
||||||
|
session_id,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_preexisting_node(self, canvas_node, session_id, core_node, name):
|
||||||
|
"""
|
||||||
|
Add preexisting nodes to grpc manager
|
||||||
|
|
||||||
|
:param str name: node_type
|
||||||
|
:param core_pb2.Node core_node: core node grpc message
|
||||||
|
:param coretk.graph.CanvasNode canvas_node: canvas node
|
||||||
|
:param int session_id: session id
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
|
||||||
|
# update the next available id
|
||||||
|
core_id = core_node.id
|
||||||
|
if self.id is None or core_id >= self.id:
|
||||||
|
self.id = core_id + 1
|
||||||
|
self.preexisting.add(core_id)
|
||||||
|
n = Node(
|
||||||
|
session_id,
|
||||||
|
core_id,
|
||||||
|
core_node.type,
|
||||||
|
core_node.model,
|
||||||
|
canvas_node.x_coord,
|
||||||
|
canvas_node.y_coord,
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
self.nodes[canvas_node.id] = n
|
||||||
|
|
||||||
|
def update_node_location(self, canvas_id, new_x, new_y):
|
||||||
|
"""
|
||||||
|
update node
|
||||||
|
|
||||||
|
:param int canvas_id: canvas id of that node
|
||||||
|
:param int new_x: new x coord
|
||||||
|
:param int new_y: new y coord
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
self.nodes[canvas_id].x = new_x
|
||||||
|
self.nodes[canvas_id].y = new_y
|
||||||
|
|
||||||
|
def update_reusable_id(self):
|
||||||
|
"""
|
||||||
|
Update available id for reuse
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if len(self.preexisting) > 0:
|
||||||
|
for i in range(1, self.id):
|
||||||
|
if i not in self.preexisting:
|
||||||
|
self.reusable.append(i)
|
||||||
|
|
||||||
|
self.preexisting.clear()
|
||||||
|
logging.debug("Next id: %s, Reusable: %s", self.id, self.reusable)
|
||||||
|
|
||||||
|
def delete_node(self, canvas_id):
|
||||||
|
"""
|
||||||
|
Delete a node from the session
|
||||||
|
|
||||||
|
:param int canvas_id: node's id in the canvas
|
||||||
|
:return: thing
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.nodes.pop(canvas_id)
|
||||||
|
self.reusable.append(canvas_id)
|
||||||
|
self.reusable.sort()
|
||||||
|
except KeyError:
|
||||||
|
logging.error("grpcmanagement.py INVALID NODE CANVAS ID")
|
||||||
|
|
||||||
|
def create_interface(self, node_type, gui_interface):
|
||||||
|
"""
|
||||||
|
create a protobuf interface given the interface object stored by the programmer
|
||||||
|
|
||||||
|
:param core_bp2.NodeType type: node type
|
||||||
|
:param coretk.interface.Interface gui_interface: the programmer's interface object
|
||||||
|
:rtype: core_bp2.Interface
|
||||||
|
:return: protobuf interface object
|
||||||
|
"""
|
||||||
|
if node_type != core_pb2.NodeType.DEFAULT:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
interface = core_pb2.Interface(
|
||||||
|
id=gui_interface.id,
|
||||||
|
name=gui_interface.name,
|
||||||
|
mac=gui_interface.mac,
|
||||||
|
ip4=gui_interface.ipv4,
|
||||||
|
ip4mask=gui_interface.ip4prefix,
|
||||||
|
)
|
||||||
|
logging.debug("create interface: %s", interface)
|
||||||
|
return interface
|
||||||
|
|
||||||
|
def create_edge_interface(self, edge, src_canvas_id, dst_canvas_id):
|
||||||
|
"""
|
||||||
|
Create the interface for the two end of an edge, add a copy to node's interfaces
|
||||||
|
|
||||||
|
:param coretk.grpcmanagement.Edge edge: edge to add interfaces to
|
||||||
|
:param int src_canvas_id: canvas id for the source node
|
||||||
|
:param int dst_canvas_id: canvas id for the destination node
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
src_interface = None
|
||||||
|
dst_interface = None
|
||||||
|
print("create interface")
|
||||||
|
self.interfaces_manager.new_subnet()
|
||||||
|
|
||||||
|
src_node = self.nodes[src_canvas_id]
|
||||||
|
if src_node.model in network_layer_nodes:
|
||||||
|
ifid = len(src_node.interfaces)
|
||||||
|
name = "eth" + str(ifid)
|
||||||
|
src_interface = Interface(
|
||||||
|
name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address())
|
||||||
|
)
|
||||||
|
self.nodes[src_canvas_id].interfaces.append(src_interface)
|
||||||
|
logging.debug(
|
||||||
|
"Create source interface 1... IP: %s, name: %s",
|
||||||
|
src_interface.ipv4,
|
||||||
|
src_interface.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
dst_node = self.nodes[dst_canvas_id]
|
||||||
|
if dst_node.model in network_layer_nodes:
|
||||||
|
ifid = len(dst_node.interfaces)
|
||||||
|
name = "eth" + str(ifid)
|
||||||
|
dst_interface = Interface(
|
||||||
|
name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address())
|
||||||
|
)
|
||||||
|
self.nodes[dst_canvas_id].interfaces.append(dst_interface)
|
||||||
|
logging.debug(
|
||||||
|
"Create destination interface... IP: %s, name: %s",
|
||||||
|
dst_interface.ipv4,
|
||||||
|
dst_interface.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
edge.interface_1 = src_interface
|
||||||
|
edge.interface_2 = dst_interface
|
||||||
|
return src_interface, dst_interface
|
||||||
|
|
||||||
|
def add_edge(self, session_id, token, canvas_id_1, canvas_id_2):
|
||||||
|
"""
|
||||||
|
Add an edge to grpc manager
|
||||||
|
|
||||||
|
:param int session_id: core session id
|
||||||
|
:param tuple(int, int) token: edge's identification in the canvas
|
||||||
|
:param int canvas_id_1: canvas id of source node
|
||||||
|
:param int canvas_id_2: canvas_id of destination node
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if canvas_id_1 in self.nodes and canvas_id_2 in self.nodes:
|
||||||
|
edge = Edge(
|
||||||
|
session_id,
|
||||||
|
self.nodes[canvas_id_1].node_id,
|
||||||
|
self.nodes[canvas_id_1].type,
|
||||||
|
self.nodes[canvas_id_2].node_id,
|
||||||
|
self.nodes[canvas_id_2].type,
|
||||||
|
)
|
||||||
|
self.edges[token] = edge
|
||||||
|
src_interface, dst_interface = self.create_edge_interface(
|
||||||
|
edge, canvas_id_1, canvas_id_2
|
||||||
|
)
|
||||||
|
node_one_id = self.nodes[canvas_id_1].node_id
|
||||||
|
node_two_id = self.nodes[canvas_id_2].node_id
|
||||||
|
|
||||||
|
# provide a way to get an edge from a core node and an interface id
|
||||||
|
if src_interface is not None:
|
||||||
|
self.core_mapping.map_node_and_interface_to_canvas_edge(
|
||||||
|
node_one_id, src_interface.id, token
|
||||||
|
)
|
||||||
|
logging.debug(
|
||||||
|
"map node id %s, interface_id %s to edge token %s",
|
||||||
|
node_one_id,
|
||||||
|
src_interface.id,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
|
||||||
|
if dst_interface is not None:
|
||||||
|
self.core_mapping.map_node_and_interface_to_canvas_edge(
|
||||||
|
node_two_id, dst_interface.id, token
|
||||||
|
)
|
||||||
|
logging.debug(
|
||||||
|
"map node id %s, interface_id %s to edge token %s",
|
||||||
|
node_two_id,
|
||||||
|
dst_interface.id,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
|
||||||
|
logging.debug("Adding edge to grpc manager...")
|
||||||
|
else:
|
||||||
|
logging.error("grpcmanagement.py INVALID CANVAS NODE ID")
|
|
@ -9,19 +9,19 @@ class CoreMenubar(object):
|
||||||
Core menubar
|
Core menubar
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, application, master, menubar):
|
def __init__(self, app, master, menubar):
|
||||||
"""
|
"""
|
||||||
Create a CoreMenubar instance
|
Create a CoreMenubar instance
|
||||||
|
|
||||||
:param master:
|
:param master:
|
||||||
:param tkinter.Menu menubar: menubar object
|
:param tkinter.Menu menubar: menubar object
|
||||||
:param coretk.app.Application application: application object
|
:param coretk.app.Application app: application object
|
||||||
"""
|
"""
|
||||||
self.menubar = menubar
|
self.menubar = menubar
|
||||||
self.master = master
|
self.master = master
|
||||||
self.application = application
|
self.app = app
|
||||||
self.menuaction = action.MenuAction(application, master)
|
self.menuaction = action.MenuAction(app, master)
|
||||||
self.menu_action = MenuAction(self.application, self.master)
|
self.menu_action = MenuAction(self.app, self.master)
|
||||||
|
|
||||||
# def on_quit(self):
|
# def on_quit(self):
|
||||||
# """
|
# """
|
||||||
|
@ -607,7 +607,7 @@ class CoreMenubar(object):
|
||||||
label="Comments...", command=action.session_comments, underline=0
|
label="Comments...", command=action.session_comments, underline=0
|
||||||
)
|
)
|
||||||
session_menu.add_command(
|
session_menu.add_command(
|
||||||
label="Hooks...", command=action.session_hooks, underline=0
|
label="Hooks...", command=self.menu_action.session_hooks, underline=0
|
||||||
)
|
)
|
||||||
session_menu.add_command(
|
session_menu.add_command(
|
||||||
label="Reset node positions",
|
label="Reset node positions",
|
||||||
|
@ -649,23 +649,23 @@ class CoreMenubar(object):
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.application.bind_all("<Control-n>", action.file_new_shortcut)
|
self.app.bind_all("<Control-n>", action.file_new_shortcut)
|
||||||
self.application.bind_all("<Control-o>", action.file_open_shortcut)
|
self.app.bind_all("<Control-o>", action.file_open_shortcut)
|
||||||
self.application.bind_all("<Control-s>", action.file_save_shortcut)
|
self.app.bind_all("<Control-s>", action.file_save_shortcut)
|
||||||
self.application.bind_all("<Control-z>", action.edit_undo_shortcut)
|
self.app.bind_all("<Control-z>", action.edit_undo_shortcut)
|
||||||
self.application.bind_all("<Control-y>", action.edit_redo_shortcut)
|
self.app.bind_all("<Control-y>", action.edit_redo_shortcut)
|
||||||
self.application.bind_all("<Control-x>", action.edit_cut_shortcut)
|
self.app.bind_all("<Control-x>", action.edit_cut_shortcut)
|
||||||
self.application.bind_all("<Control-c>", action.edit_copy_shortcut)
|
self.app.bind_all("<Control-c>", action.edit_copy_shortcut)
|
||||||
self.application.bind_all("<Control-v>", action.edit_paste_shortcut)
|
self.app.bind_all("<Control-v>", action.edit_paste_shortcut)
|
||||||
self.application.bind_all("<Control-a>", action.edit_select_all_shortcut)
|
self.app.bind_all("<Control-a>", action.edit_select_all_shortcut)
|
||||||
self.application.bind_all("<Control-j>", action.edit_select_adjacent_shortcut)
|
self.app.bind_all("<Control-j>", action.edit_select_adjacent_shortcut)
|
||||||
self.application.bind_all("<Control-f>", action.edit_find_shortcut)
|
self.app.bind_all("<Control-f>", action.edit_find_shortcut)
|
||||||
self.application.bind_all("<Prior>", action.canvas_previous_shortcut)
|
self.app.bind_all("<Prior>", action.canvas_previous_shortcut)
|
||||||
self.application.bind_all("<Next>", action.canvas_next_shortcut)
|
self.app.bind_all("<Next>", action.canvas_next_shortcut)
|
||||||
self.application.bind_all("<Home>", action.canvas_first_shortcut)
|
self.app.bind_all("<Home>", action.canvas_first_shortcut)
|
||||||
self.application.bind_all("<End>", action.canvas_last_shortcut)
|
self.app.bind_all("<End>", action.canvas_last_shortcut)
|
||||||
self.application.bind_all("<Control-Shift-plus>", action.view_zoom_in_shortcut)
|
self.app.bind_all("<Control-Shift-plus>", action.view_zoom_in_shortcut)
|
||||||
self.application.bind_all("<Control-minus>", action.view_zoom_out_shortcut)
|
self.app.bind_all("<Control-minus>", action.view_zoom_out_shortcut)
|
||||||
|
|
||||||
def create_core_menubar(self):
|
def create_core_menubar(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -8,7 +8,6 @@ class CoreToCanvasMapping:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.core_id_to_canvas_id = {}
|
self.core_id_to_canvas_id = {}
|
||||||
self.core_node_and_interface_to_canvas_edge = {}
|
self.core_node_and_interface_to_canvas_edge = {}
|
||||||
# self.edge_id_to_canvas_token = {}
|
|
||||||
|
|
||||||
def map_node_and_interface_to_canvas_edge(self, nid, iid, edge_token):
|
def map_node_and_interface_to_canvas_edge(self, nid, iid, edge_token):
|
||||||
self.core_node_and_interface_to_canvas_edge[tuple([nid, iid])] = edge_token
|
self.core_node_and_interface_to_canvas_edge[tuple([nid, iid])] = edge_token
|
||||||
|
@ -33,13 +32,3 @@ class CoreToCanvasMapping:
|
||||||
else:
|
else:
|
||||||
logging.debug("invalid key")
|
logging.debug("invalid key")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# def add_mapping(self, core_id, canvas_id):
|
|
||||||
# if core_id not in self.core_id_to_canvas_id:
|
|
||||||
# self.core_id_to_canvas_id[core_id] = canvas_id
|
|
||||||
# else:
|
|
||||||
# logging.error("key already mapped")
|
|
||||||
#
|
|
||||||
# def delete_mapping(self, core_id):
|
|
||||||
# result = self.core_id_to_canvas_id.pop(core_id, None)
|
|
||||||
# return result
|
|
||||||
|
|
|
@ -25,14 +25,14 @@ class CoreToolbar(object):
|
||||||
Core toolbar class
|
Core toolbar class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, application, edit_frame, menubar):
|
def __init__(self, app, edit_frame, menubar):
|
||||||
"""
|
"""
|
||||||
Create a CoreToolbar instance
|
Create a CoreToolbar instance
|
||||||
|
|
||||||
:param tkinter.Frame edit_frame: edit frame
|
:param tkinter.Frame edit_frame: edit frame
|
||||||
"""
|
"""
|
||||||
self.application = application
|
self.app = app
|
||||||
self.master = application.master
|
self.master = app.master
|
||||||
self.edit_frame = edit_frame
|
self.edit_frame = edit_frame
|
||||||
self.menubar = menubar
|
self.menubar = menubar
|
||||||
self.radio_value = tk.IntVar()
|
self.radio_value = tk.IntVar()
|
||||||
|
@ -161,7 +161,7 @@ class CoreToolbar(object):
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
logging.debug("Click START STOP SESSION button")
|
logging.debug("Click START STOP SESSION button")
|
||||||
helper = CoreToolbarHelp(self.application)
|
helper = CoreToolbarHelp(self.app)
|
||||||
self.destroy_children_widgets()
|
self.destroy_children_widgets()
|
||||||
self.canvas.mode = GraphMode.SELECT
|
self.canvas.mode = GraphMode.SELECT
|
||||||
|
|
||||||
|
@ -593,11 +593,7 @@ class CoreToolbar(object):
|
||||||
"""
|
"""
|
||||||
logging.debug("Click on STOP button ")
|
logging.debug("Click on STOP button ")
|
||||||
self.destroy_children_widgets()
|
self.destroy_children_widgets()
|
||||||
|
self.app.core.stop_session()
|
||||||
# self.canvas.core_grpc.set_session_state(SessionStateEnum.DATACOLLECT.value)
|
|
||||||
# self.canvas.core_grpc.delete_links()
|
|
||||||
# self.canvas.core_grpc.delete_nodes()
|
|
||||||
self.canvas.core_grpc.stop_session()
|
|
||||||
self.create_toolbar()
|
self.create_toolbar()
|
||||||
|
|
||||||
def click_run_button(self):
|
def click_run_button(self):
|
||||||
|
|
|
@ -5,9 +5,8 @@ from core.api.grpc.client import core_pb2
|
||||||
|
|
||||||
|
|
||||||
class CoreToolbarHelp:
|
class CoreToolbarHelp:
|
||||||
def __init__(self, application):
|
def __init__(self, app):
|
||||||
self.application = application
|
self.app = app
|
||||||
self.core_grpc = application.core_grpc
|
|
||||||
|
|
||||||
def get_node_list(self):
|
def get_node_list(self):
|
||||||
"""
|
"""
|
||||||
|
@ -15,12 +14,8 @@ class CoreToolbarHelp:
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
grpc_manager = self.application.canvas.grpc_manager
|
|
||||||
|
|
||||||
# list(core_pb2.Node)
|
|
||||||
nodes = []
|
nodes = []
|
||||||
|
for node in self.app.core.nodes.values():
|
||||||
for node in grpc_manager.nodes.values():
|
|
||||||
pos = core_pb2.Position(x=int(node.x), y=int(node.y))
|
pos = core_pb2.Position(x=int(node.x), y=int(node.y))
|
||||||
n = core_pb2.Node(
|
n = core_pb2.Node(
|
||||||
id=node.node_id, type=node.type, position=pos, model=node.model
|
id=node.node_id, type=node.type, position=pos, model=node.model
|
||||||
|
@ -35,38 +30,26 @@ class CoreToolbarHelp:
|
||||||
:rtype: list(core_pb2.Link)
|
:rtype: list(core_pb2.Link)
|
||||||
:return: list of protobuf links
|
:return: list of protobuf links
|
||||||
"""
|
"""
|
||||||
grpc_manager = self.application.canvas.grpc_manager
|
|
||||||
|
|
||||||
# list(core_bp2.Link)
|
|
||||||
links = []
|
links = []
|
||||||
for edge in grpc_manager.edges.values():
|
for edge in self.app.core.edges.values():
|
||||||
interface_one = self.application.core_grpc.create_interface(
|
interface_one = self.app.core.create_interface(edge.type1, edge.interface_1)
|
||||||
edge.type1, edge.interface_1
|
interface_two = self.app.core.create_interface(edge.type2, edge.interface_2)
|
||||||
)
|
|
||||||
interface_two = self.application.core_grpc.create_interface(
|
|
||||||
edge.type2, edge.interface_2
|
|
||||||
)
|
|
||||||
# TODO for now only consider the basic cases
|
# TODO for now only consider the basic cases
|
||||||
if (
|
# if (
|
||||||
edge.type1 == core_pb2.NodeType.WIRELESS_LAN
|
# edge.type1 == core_pb2.NodeType.WIRELESS_LAN
|
||||||
or edge.type2 == core_pb2.NodeType.WIRELESS_LAN
|
# or edge.type2 == core_pb2.NodeType.WIRELESS_LAN
|
||||||
):
|
# ):
|
||||||
link_type = core_pb2.LinkType.WIRELESS
|
# link_type = core_pb2.LinkType.WIRELESS
|
||||||
else:
|
# else:
|
||||||
link_type = core_pb2.LinkType.WIRED
|
# link_type = core_pb2.LinkType.WIRED
|
||||||
link = core_pb2.Link(
|
link = core_pb2.Link(
|
||||||
node_one_id=edge.id1,
|
node_one_id=edge.id1,
|
||||||
node_two_id=edge.id2,
|
node_two_id=edge.id2,
|
||||||
type=link_type,
|
type=core_pb2.LinkType.WIRED,
|
||||||
interface_one=interface_one,
|
interface_one=interface_one,
|
||||||
interface_two=interface_two,
|
interface_two=interface_two,
|
||||||
)
|
)
|
||||||
links.append(link)
|
links.append(link)
|
||||||
# self.id1 = edge.id1
|
|
||||||
# self.id2 = edge.id2
|
|
||||||
# self.type = link_type
|
|
||||||
# self.if1 = interface_one
|
|
||||||
# self.if2 = interface_two
|
|
||||||
|
|
||||||
return links
|
return links
|
||||||
|
|
||||||
|
@ -77,8 +60,7 @@ class CoreToolbarHelp:
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
configs = []
|
configs = []
|
||||||
grpc_manager = self.application.canvas.grpc_manager
|
manager_configs = self.app.core.wlanconfig_management.configurations
|
||||||
manager_configs = grpc_manager.wlanconfig_management.configurations
|
|
||||||
for key in manager_configs:
|
for key in manager_configs:
|
||||||
cnf = core_pb2.WlanConfig(node_id=key, config=manager_configs[key])
|
cnf = core_pb2.WlanConfig(node_id=key, config=manager_configs[key])
|
||||||
configs.append(cnf)
|
configs.append(cnf)
|
||||||
|
@ -91,8 +73,8 @@ class CoreToolbarHelp:
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
configs = []
|
configs = []
|
||||||
grpc_manager = self.application.canvas.grpc_manager
|
core = self.app.canvas.core
|
||||||
manager_configs = grpc_manager.mobilityconfig_management.configurations
|
manager_configs = core.mobilityconfig_management.configurations
|
||||||
for key in manager_configs:
|
for key in manager_configs:
|
||||||
cnf = core_pb2.MobilityConfig(node_id=key, config=manager_configs[key])
|
cnf = core_pb2.MobilityConfig(node_id=key, config=manager_configs[key])
|
||||||
configs.append(cnf)
|
configs.append(cnf)
|
||||||
|
@ -103,35 +85,6 @@ class CoreToolbarHelp:
|
||||||
links = self.get_link_list()
|
links = self.get_link_list()
|
||||||
wlan_configs = self.get_wlan_configuration_list()
|
wlan_configs = self.get_wlan_configuration_list()
|
||||||
mobility_configs = self.get_mobility_configuration_list()
|
mobility_configs = self.get_mobility_configuration_list()
|
||||||
|
self.app.core.start_session(
|
||||||
self.core_grpc.start_session(
|
|
||||||
nodes, links, wlan_configs=wlan_configs, mobility_configs=mobility_configs
|
nodes, links, wlan_configs=wlan_configs, mobility_configs=mobility_configs
|
||||||
)
|
)
|
||||||
# self.core_grpc.core.add_link(self.core_grpc.session_id, self.id1, self.id2, self.if1, self.if2)
|
|
||||||
# res = self.core_grpc.core.get_wlan_config(self.core_grpc.session_id, 1)
|
|
||||||
|
|
||||||
# res = self.core_grpc.core.get_wlan_config(self.core_grpc.session_id, 2)
|
|
||||||
|
|
||||||
# print(res)
|
|
||||||
|
|
||||||
# def add_nodes(self):
|
|
||||||
# """
|
|
||||||
# add the nodes stored in grpc manager
|
|
||||||
# :return: nothing
|
|
||||||
# """
|
|
||||||
# grpc_manager = self.application.canvas.grpc_manager
|
|
||||||
# for node in grpc_manager.nodes.values():
|
|
||||||
# self.application.core_grpc.add_node(
|
|
||||||
# node.type, node.model, int(node.x), int(node.y), node.name, node.node_id
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# def add_edges(self):
|
|
||||||
# """
|
|
||||||
# add the edges stored in grpc manager
|
|
||||||
# :return:
|
|
||||||
# """
|
|
||||||
# grpc_manager = self.application.canvas.grpc_manager
|
|
||||||
# for edge in grpc_manager.edges.values():
|
|
||||||
# self.application.core_grpc.add_link(
|
|
||||||
# edge.id1, edge.id2, edge.type1, edge.type2, edge
|
|
||||||
# )
|
|
||||||
|
|
|
@ -17,8 +17,9 @@ class Dialog(tk.Toplevel):
|
||||||
def show(self):
|
def show(self):
|
||||||
self.transient(self.master)
|
self.transient(self.master)
|
||||||
self.focus_force()
|
self.focus_force()
|
||||||
if self.modal:
|
|
||||||
self.grab_set()
|
|
||||||
self.update()
|
self.update()
|
||||||
self.deiconify()
|
self.deiconify()
|
||||||
|
if self.modal:
|
||||||
|
self.wait_visibility()
|
||||||
|
self.grab_set()
|
||||||
self.wait_window()
|
self.wait_window()
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
emane configuration
|
emane configuration
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
from coretk.dialogs.dialog import Dialog
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.dialogs.mobilityconfig import MobilityConfiguration
|
||||||
from coretk.images import ImageEnum, Images
|
from coretk.images import ImageEnum, Images
|
||||||
|
|
||||||
|
|
||||||
class EmaneConfiguration(Dialog):
|
class EmaneConfiguration(Dialog):
|
||||||
def __init__(self, master, app, canvas_node):
|
def __init__(self, master, app, canvas_node):
|
||||||
super().__init__(master, app, "emane configuration", modal=False)
|
super().__init__(master, app, "emane configuration", modal=False)
|
||||||
|
self.app = app
|
||||||
self.canvas_node = canvas_node
|
self.canvas_node = canvas_node
|
||||||
self.radiovar = tk.IntVar()
|
self.radiovar = tk.IntVar()
|
||||||
self.radiovar.set(1)
|
self.radiovar.set(1)
|
||||||
|
@ -20,6 +23,9 @@ class EmaneConfiguration(Dialog):
|
||||||
# draw
|
# draw
|
||||||
self.node_name_and_image()
|
self.node_name_and_image()
|
||||||
self.emane_configuration()
|
self.emane_configuration()
|
||||||
|
self.draw_ip_subnets()
|
||||||
|
self.emane_options()
|
||||||
|
self.draw_apply_and_cancel()
|
||||||
|
|
||||||
def browse_emane_wiki(self):
|
def browse_emane_wiki(self):
|
||||||
webbrowser.open_new("https://github.com/adjacentlink/emane/wiki")
|
webbrowser.open_new("https://github.com/adjacentlink/emane/wiki")
|
||||||
|
@ -59,10 +65,12 @@ class EmaneConfiguration(Dialog):
|
||||||
b = tk.Button(f, image=self.canvas_node.image)
|
b = tk.Button(f, image=self.canvas_node.image)
|
||||||
b.grid(row=0, column=3, padx=2, pady=2)
|
b.grid(row=0, column=3, padx=2, pady=2)
|
||||||
|
|
||||||
f.grid(row=0, column=0)
|
f.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
|
||||||
def draw_option_buttons(self, parent):
|
def draw_option_buttons(self, parent):
|
||||||
f = tk.Frame(parent, bg="#d9d9d9")
|
f = tk.Frame(parent, bg="#d9d9d9")
|
||||||
|
f.columnconfigure(0, weight=1)
|
||||||
|
f.columnconfigure(1, weight=1)
|
||||||
b = tk.Button(
|
b = tk.Button(
|
||||||
f,
|
f,
|
||||||
text="model options",
|
text="model options",
|
||||||
|
@ -71,7 +79,7 @@ class EmaneConfiguration(Dialog):
|
||||||
bg="#d9d9d9",
|
bg="#d9d9d9",
|
||||||
state=tk.DISABLED,
|
state=tk.DISABLED,
|
||||||
)
|
)
|
||||||
b.grid(row=0, column=0, padx=2, pady=2)
|
b.grid(row=0, column=0, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
b = tk.Button(
|
b = tk.Button(
|
||||||
f,
|
f,
|
||||||
text="EMANE options",
|
text="EMANE options",
|
||||||
|
@ -79,11 +87,43 @@ class EmaneConfiguration(Dialog):
|
||||||
compound=tk.RIGHT,
|
compound=tk.RIGHT,
|
||||||
bg="#d9d9d9",
|
bg="#d9d9d9",
|
||||||
)
|
)
|
||||||
b.grid(row=0, column=1, padx=2, pady=2)
|
b.grid(row=0, column=1, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
f.grid(row=4, column=0)
|
f.grid(row=4, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
|
||||||
|
def radiobutton_text(self, val):
|
||||||
|
"""
|
||||||
|
get appropriate text based on radio value
|
||||||
|
|
||||||
|
:return: the text value to configure button
|
||||||
|
"""
|
||||||
|
if val == 1:
|
||||||
|
return "none"
|
||||||
|
elif val == 2:
|
||||||
|
return "rfpipe options"
|
||||||
|
elif val == 3:
|
||||||
|
return "ieee80211abg options"
|
||||||
|
elif val == 4:
|
||||||
|
return "commeffect options"
|
||||||
|
elif val == 5:
|
||||||
|
return "bypass options"
|
||||||
|
elif val == 6:
|
||||||
|
return "tdma options"
|
||||||
|
else:
|
||||||
|
logging.debug("emaneconfig.py invalid radio value")
|
||||||
|
return ""
|
||||||
|
|
||||||
def click_radio_button(self):
|
def click_radio_button(self):
|
||||||
print(self.radiovar.get())
|
print(type(self.radiovar.get()))
|
||||||
|
config_frame = self.grid_slaves(row=2, column=0)[0]
|
||||||
|
option_button_frame = config_frame.grid_slaves(row=4, column=0)[0]
|
||||||
|
b = option_button_frame.grid_slaves(row=0, column=0)[0]
|
||||||
|
text = self.radiobutton_text(self.radiovar.get())
|
||||||
|
if text == "none":
|
||||||
|
state = tk.DISABLED
|
||||||
|
else:
|
||||||
|
state = tk.NORMAL
|
||||||
|
b.config(text=text, state=state)
|
||||||
|
# b.config(text=)
|
||||||
|
|
||||||
def draw_emane_models(self, parent):
|
def draw_emane_models(self, parent):
|
||||||
models = ["none", "rfpipe", "ieee80211abg", "commeffect", "bypass", "tdma"]
|
models = ["none", "rfpipe", "ieee80211abg", "commeffect", "bypass", "tdma"]
|
||||||
|
@ -111,6 +151,21 @@ class EmaneConfiguration(Dialog):
|
||||||
value = value + 1
|
value = value + 1
|
||||||
f.grid(row=3, column=0, sticky=tk.W + tk.E)
|
f.grid(row=3, column=0, sticky=tk.W + tk.E)
|
||||||
|
|
||||||
|
def draw_text_label_and_entry(self, parent, label_text, entry_text):
|
||||||
|
"""
|
||||||
|
draw a label and an entry on a single row
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
var = tk.StringVar()
|
||||||
|
var.set(entry_text)
|
||||||
|
f = tk.Frame(parent)
|
||||||
|
lbl = tk.Label(f, text=label_text)
|
||||||
|
lbl.grid(row=0, column=0)
|
||||||
|
e = tk.Entry(f, textvariable=var, bg="white")
|
||||||
|
e.grid(row=0, column=1)
|
||||||
|
f.grid(stick=tk.W)
|
||||||
|
|
||||||
def emane_configuration(self):
|
def emane_configuration(self):
|
||||||
lbl = tk.Label(self, text="Emane")
|
lbl = tk.Label(self, text="Emane")
|
||||||
lbl.grid(row=1, column=0)
|
lbl.grid(row=1, column=0)
|
||||||
|
@ -142,10 +197,54 @@ class EmaneConfiguration(Dialog):
|
||||||
"\nusing pluggable MAC and PHY modules. Refer to the wiki for configuration option details",
|
"\nusing pluggable MAC and PHY modules. Refer to the wiki for configuration option details",
|
||||||
bg="#d9d9d9",
|
bg="#d9d9d9",
|
||||||
)
|
)
|
||||||
lbl.grid(row=1, column=0, sticky=tk.W)
|
lbl.grid(row=1, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
|
||||||
lbl = tk.Label(f, text="EMANE Models", bg="#d9d9d9")
|
lbl = tk.Label(f, text="EMANE Models", bg="#d9d9d9")
|
||||||
lbl.grid(row=2, column=0, sticky=tk.W)
|
lbl.grid(row=2, column=0, sticky=tk.W)
|
||||||
self.draw_option_buttons(f)
|
self.draw_option_buttons(f)
|
||||||
self.draw_emane_models(f)
|
self.draw_emane_models(f)
|
||||||
f.grid(row=2, column=0)
|
f.grid(row=2, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
|
||||||
|
def draw_ip_subnets(self):
|
||||||
|
self.draw_text_label_and_entry(self, "IPv4 subnet", "")
|
||||||
|
self.draw_text_label_and_entry(self, "IPv6 subnet", "")
|
||||||
|
|
||||||
|
def click_ns2_mobility_script(self):
|
||||||
|
dialog = MobilityConfiguration(self, self.app, self.canvas_node)
|
||||||
|
dialog.show()
|
||||||
|
|
||||||
|
def emane_options(self):
|
||||||
|
"""
|
||||||
|
create wireless node options
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
f = tk.Frame(self)
|
||||||
|
f.columnconfigure(0, weight=1)
|
||||||
|
f.columnconfigure(1, weight=1)
|
||||||
|
f.columnconfigure(2, weight=1)
|
||||||
|
b = tk.Button(
|
||||||
|
f,
|
||||||
|
text="ns-2 mobility script...",
|
||||||
|
command=lambda: self.click_ns2_mobility_script(),
|
||||||
|
)
|
||||||
|
# b.pack(side=tk.LEFT, padx=1)
|
||||||
|
b.grid(row=0, column=0, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
b = tk.Button(f, text="Link to all routers")
|
||||||
|
b.grid(row=0, column=1, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
# b.pack(side=tk.LEFT, padx=1)
|
||||||
|
b = tk.Button(f, text="Choose WLAN members")
|
||||||
|
b.grid(row=0, column=2, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
# b.pack(side=tk.LEFT, padx=1)
|
||||||
|
f.grid(row=5, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
|
||||||
|
def draw_apply_and_cancel(self):
|
||||||
|
f = tk.Frame(self, bg="#d9d9d9")
|
||||||
|
f.columnconfigure(0, weight=1)
|
||||||
|
f.columnconfigure(1, weight=1)
|
||||||
|
b = tk.Button(f, text="Apply", bg="#d9d9d9")
|
||||||
|
b.grid(row=0, column=0, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
b = tk.Button(f, text="Cancel", bg="#d9d9d9", command=self.destroy)
|
||||||
|
b.grid(row=0, column=1, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
|
||||||
|
f.grid(sticky=tk.N + tk.S + tk.E + tk.W)
|
||||||
|
|
153
coretk/coretk/dialogs/hooks.py
Normal file
153
coretk/coretk/dialogs/hooks.py
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
|
||||||
|
from core.api.grpc import core_pb2
|
||||||
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
|
||||||
|
|
||||||
|
class HookDialog(Dialog):
|
||||||
|
def __init__(self, master, app):
|
||||||
|
super().__init__(master, app, "Hook", modal=True)
|
||||||
|
self.name = tk.StringVar()
|
||||||
|
self.data = None
|
||||||
|
self.hook = core_pb2.Hook()
|
||||||
|
self.state = tk.StringVar()
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
self.rowconfigure(1, weight=1)
|
||||||
|
|
||||||
|
# name and states
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=0, sticky="ew", pady=2)
|
||||||
|
frame.columnconfigure(0, weight=2)
|
||||||
|
frame.columnconfigure(1, weight=7)
|
||||||
|
frame.columnconfigure(2, weight=1)
|
||||||
|
label = tk.Label(frame, text="Name")
|
||||||
|
label.grid(row=0, column=0, sticky="ew")
|
||||||
|
entry = tk.Entry(frame, textvariable=self.name)
|
||||||
|
entry.grid(row=0, column=1, sticky="ew")
|
||||||
|
values = tuple(x for x in core_pb2.SessionState.Enum.keys() if x != "NONE")
|
||||||
|
initial_state = core_pb2.SessionState.Enum.Name(core_pb2.SessionState.RUNTIME)
|
||||||
|
self.state.set(initial_state)
|
||||||
|
self.name.set(f"{initial_state.lower()}_hook.sh")
|
||||||
|
combobox = ttk.Combobox(frame, textvariable=self.state, values=values)
|
||||||
|
combobox.grid(row=0, column=2, sticky="ew")
|
||||||
|
combobox.bind("<<ComboboxSelected>>", self.state_change)
|
||||||
|
|
||||||
|
# data
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.rowconfigure(0, weight=1)
|
||||||
|
frame.grid(row=1, sticky="nsew", pady=2)
|
||||||
|
self.data = tk.Text(frame)
|
||||||
|
self.data.insert(
|
||||||
|
1.0,
|
||||||
|
(
|
||||||
|
"#!/bin/sh\n"
|
||||||
|
"# session hook script; write commands here to execute on the host at the\n"
|
||||||
|
"# specified state\n"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
self.data.grid(row=0, column=0, sticky="nsew")
|
||||||
|
scrollbar = tk.Scrollbar(frame)
|
||||||
|
scrollbar.grid(row=0, column=1, sticky="ns")
|
||||||
|
self.data.config(yscrollcommand=scrollbar.set)
|
||||||
|
scrollbar.config(command=self.data.yview)
|
||||||
|
|
||||||
|
# button row
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=2, sticky="ew", pady=2)
|
||||||
|
for i in range(2):
|
||||||
|
frame.columnconfigure(i, weight=1)
|
||||||
|
button = tk.Button(frame, text="Save", command=lambda: self.save())
|
||||||
|
button.grid(row=0, column=0, sticky="ew")
|
||||||
|
button = tk.Button(frame, text="Cancel", command=lambda: self.destroy())
|
||||||
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
def state_change(self, event):
|
||||||
|
state_name = self.state.get()
|
||||||
|
self.name.set(f"{state_name.lower()}_hook.sh")
|
||||||
|
|
||||||
|
def set(self, hook):
|
||||||
|
self.hook = hook
|
||||||
|
self.name.set(hook.file)
|
||||||
|
self.data.delete(1.0, tk.END)
|
||||||
|
self.data.insert(tk.END, hook.data)
|
||||||
|
state_name = core_pb2.SessionState.Enum.Name(hook.state)
|
||||||
|
self.state.set(state_name)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
data = self.data.get("1.0", tk.END).strip()
|
||||||
|
state_value = core_pb2.SessionState.Enum.Value(self.state.get())
|
||||||
|
self.hook.file = self.name.get()
|
||||||
|
self.hook.data = data
|
||||||
|
self.hook.state = state_value
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
class HooksDialog(Dialog):
|
||||||
|
def __init__(self, master, app):
|
||||||
|
super().__init__(master, app, "Hooks", modal=True)
|
||||||
|
self.listbox = None
|
||||||
|
self.edit_button = None
|
||||||
|
self.delete_button = None
|
||||||
|
self.selected = None
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
self.rowconfigure(0, weight=1)
|
||||||
|
self.listbox = tk.Listbox(self)
|
||||||
|
self.listbox.grid(row=0, sticky="nsew")
|
||||||
|
self.listbox.bind("<<ListboxSelect>>", self.select)
|
||||||
|
for hook_file in self.app.core.hooks:
|
||||||
|
self.listbox.insert(tk.END, hook_file)
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=1, sticky="ew")
|
||||||
|
for i in range(4):
|
||||||
|
frame.columnconfigure(i, weight=1)
|
||||||
|
button = tk.Button(frame, text="Create", command=self.click_create)
|
||||||
|
button.grid(row=0, column=0, sticky="ew")
|
||||||
|
self.edit_button = tk.Button(
|
||||||
|
frame, text="Edit", state=tk.DISABLED, command=self.click_edit
|
||||||
|
)
|
||||||
|
self.edit_button.grid(row=0, column=1, sticky="ew")
|
||||||
|
self.delete_button = tk.Button(
|
||||||
|
frame, text="Delete", state=tk.DISABLED, command=self.click_delete
|
||||||
|
)
|
||||||
|
self.delete_button.grid(row=0, column=2, sticky="ew")
|
||||||
|
button = tk.Button(frame, text="Cancel", command=lambda: self.destroy())
|
||||||
|
button.grid(row=0, column=3, sticky="ew")
|
||||||
|
|
||||||
|
def click_create(self):
|
||||||
|
dialog = HookDialog(self, self.app)
|
||||||
|
dialog.show()
|
||||||
|
hook = dialog.hook
|
||||||
|
if hook:
|
||||||
|
self.app.core.hooks[hook.file] = hook
|
||||||
|
self.listbox.insert(tk.END, hook.file)
|
||||||
|
|
||||||
|
def click_edit(self):
|
||||||
|
hook = self.app.core.hooks[self.selected]
|
||||||
|
dialog = HookDialog(self, self.app)
|
||||||
|
dialog.set(hook)
|
||||||
|
dialog.show()
|
||||||
|
|
||||||
|
def click_delete(self):
|
||||||
|
del self.app.core.hooks[self.selected]
|
||||||
|
self.listbox.delete(tk.ANCHOR)
|
||||||
|
self.edit_button.config(state=tk.DISABLED)
|
||||||
|
self.delete_button.config(state=tk.DISABLED)
|
||||||
|
|
||||||
|
def select(self, event):
|
||||||
|
if self.listbox.curselection():
|
||||||
|
index = self.listbox.curselection()[0]
|
||||||
|
self.selected = self.listbox.get(index)
|
||||||
|
self.edit_button.config(state=tk.NORMAL)
|
||||||
|
self.delete_button.config(state=tk.NORMAL)
|
||||||
|
else:
|
||||||
|
self.selected = None
|
||||||
|
self.edit_button.config(state=tk.DISABLED)
|
||||||
|
self.delete_button.config(state=tk.DISABLED)
|
|
@ -20,7 +20,8 @@ class MobilityConfiguration(Dialog):
|
||||||
"""
|
"""
|
||||||
super().__init__(master, app, "ns2script configuration", modal=True)
|
super().__init__(master, app, "ns2script configuration", modal=True)
|
||||||
self.canvas_node = canvas_node
|
self.canvas_node = canvas_node
|
||||||
self.node_config = app.canvas.grpc_manager.mobilityconfig_management.configurations[
|
print(app.canvas.core.mobilityconfig_management.configurations)
|
||||||
|
self.node_config = app.canvas.core.mobilityconfig_management.configurations[
|
||||||
canvas_node.core_id
|
canvas_node.core_id
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -209,7 +210,7 @@ class MobilityConfiguration(Dialog):
|
||||||
loop = "1"
|
loop = "1"
|
||||||
else:
|
else:
|
||||||
loop = "0"
|
loop = "0"
|
||||||
self.app.canvas.grpc_manager.mobilityconfig_management.set_custom_configuration(
|
self.app.canvas.core.mobilityconfig_management.set_custom_configuration(
|
||||||
node_id=self.canvas_node.core_id,
|
node_id=self.canvas_node.core_id,
|
||||||
file=file,
|
file=file,
|
||||||
refresh_ms=refresh_time,
|
refresh_ms=refresh_time,
|
||||||
|
|
94
coretk/coretk/dialogs/nodeconfig.py
Normal file
94
coretk/coretk/dialogs/nodeconfig.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
|
||||||
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.dialogs.nodeicon import NodeIconDialog
|
||||||
|
from coretk.dialogs.nodeservice import NodeServices
|
||||||
|
|
||||||
|
NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"]
|
||||||
|
DEFAULTNODES = ["router", "host", "PC"]
|
||||||
|
|
||||||
|
|
||||||
|
class NodeConfigDialog(Dialog):
|
||||||
|
def __init__(self, master, app, canvas_node):
|
||||||
|
"""
|
||||||
|
create an instance of node configuration
|
||||||
|
|
||||||
|
:param master: dialog master
|
||||||
|
:param coretk.app.Application: main app
|
||||||
|
:param coretk.graph.CanvasNode canvas_node: canvas node object
|
||||||
|
"""
|
||||||
|
super().__init__(master, app, f"{canvas_node.name} Configuration", modal=True)
|
||||||
|
self.canvas_node = canvas_node
|
||||||
|
self.image = canvas_node.image
|
||||||
|
self.image_button = None
|
||||||
|
self.name = tk.StringVar(value=canvas_node.name)
|
||||||
|
self.type = tk.StringVar(value=canvas_node.node_type)
|
||||||
|
self.server = tk.StringVar()
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
self.draw_first_row()
|
||||||
|
self.draw_second_row()
|
||||||
|
self.draw_third_row()
|
||||||
|
|
||||||
|
def draw_first_row(self):
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=0, column=0, pady=2, sticky="ew")
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=1)
|
||||||
|
frame.columnconfigure(2, weight=1)
|
||||||
|
|
||||||
|
entry = tk.Entry(frame, textvariable=self.name)
|
||||||
|
entry.grid(row=0, column=0, padx=2, sticky="ew")
|
||||||
|
|
||||||
|
combobox = ttk.Combobox(frame, textvariable=self.type, values=DEFAULTNODES)
|
||||||
|
combobox.grid(row=0, column=1, padx=2, sticky="ew")
|
||||||
|
|
||||||
|
combobox = ttk.Combobox(frame, textvariable=self.server, values=["localhost"])
|
||||||
|
combobox.current(0)
|
||||||
|
combobox.grid(row=0, column=2, sticky="ew")
|
||||||
|
|
||||||
|
def draw_second_row(self):
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=1, column=0, pady=2, sticky="ew")
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
|
button = tk.Button(frame, text="Services", command=lambda: NodeServices())
|
||||||
|
button.grid(row=0, column=0, padx=2, sticky="ew")
|
||||||
|
|
||||||
|
self.image_button = tk.Button(
|
||||||
|
frame,
|
||||||
|
text="Icon",
|
||||||
|
image=self.image,
|
||||||
|
compound=tk.LEFT,
|
||||||
|
command=self.click_icon,
|
||||||
|
)
|
||||||
|
self.image_button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
def draw_third_row(self):
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=2, column=0, sticky="ew")
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
|
button = tk.Button(frame, text="Apply", command=self.config_apply)
|
||||||
|
button.grid(row=0, column=0, padx=2, sticky="ew")
|
||||||
|
|
||||||
|
button = tk.Button(frame, text="Cancel", command=self.destroy)
|
||||||
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
def click_icon(self):
|
||||||
|
dialog = NodeIconDialog(self, self.app, self.canvas_node)
|
||||||
|
dialog.show()
|
||||||
|
if dialog.image:
|
||||||
|
self.image = dialog.image
|
||||||
|
self.image_button.config(image=self.image)
|
||||||
|
|
||||||
|
def config_apply(self):
|
||||||
|
self.canvas_node.name = self.name.get()
|
||||||
|
self.canvas_node.image = self.image
|
||||||
|
self.canvas_node.canvas.itemconfig(self.canvas_node.id, image=self.image)
|
||||||
|
self.destroy()
|
69
coretk/coretk/dialogs/nodeicon.py
Normal file
69
coretk/coretk/dialogs/nodeicon.py
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import filedialog
|
||||||
|
|
||||||
|
from coretk.appdirs import ICONS_PATH
|
||||||
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.images import Images
|
||||||
|
|
||||||
|
|
||||||
|
class NodeIconDialog(Dialog):
|
||||||
|
def __init__(self, master, app, canvas_node):
|
||||||
|
"""
|
||||||
|
create an instance of ImageModification
|
||||||
|
:param master: dialog master
|
||||||
|
:param coretk.app.Application: main app
|
||||||
|
:param coretk.graph.CanvasNode canvas_node: node object
|
||||||
|
"""
|
||||||
|
super().__init__(master, app, f"{canvas_node.name} Icon", modal=True)
|
||||||
|
self.file_path = tk.StringVar()
|
||||||
|
self.image_label = None
|
||||||
|
self.image = canvas_node.image
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
|
# row one
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=0, column=0, pady=2, sticky="ew")
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=3)
|
||||||
|
label = tk.Label(frame, text="Image")
|
||||||
|
label.grid(row=0, column=0, sticky="ew")
|
||||||
|
entry = tk.Entry(frame, textvariable=self.file_path)
|
||||||
|
entry.grid(row=0, column=1, sticky="ew")
|
||||||
|
button = tk.Button(frame, text="...", command=self.click_file)
|
||||||
|
button.grid(row=0, column=2)
|
||||||
|
|
||||||
|
# row two
|
||||||
|
self.image_label = tk.Label(self, image=self.image)
|
||||||
|
self.image_label.grid(row=1, column=0, pady=2, sticky="ew")
|
||||||
|
|
||||||
|
# row three
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
frame.grid(row=2, column=0, sticky="ew")
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=1)
|
||||||
|
button = tk.Button(frame, text="Apply", command=self.destroy)
|
||||||
|
button.grid(row=0, column=0, sticky="ew")
|
||||||
|
|
||||||
|
button = tk.Button(frame, text="Cancel", command=self.click_cancel)
|
||||||
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
def click_file(self):
|
||||||
|
file_path = filedialog.askopenfilename(
|
||||||
|
initialdir=str(ICONS_PATH),
|
||||||
|
title="Open",
|
||||||
|
filetypes=(
|
||||||
|
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
|
||||||
|
("All Files", "*"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if file_path:
|
||||||
|
self.image = Images.create(file_path)
|
||||||
|
self.image_label.config(image=self.image)
|
||||||
|
self.file_path.set(file_path)
|
||||||
|
|
||||||
|
def click_cancel(self):
|
||||||
|
self.image = None
|
||||||
|
self.destroy()
|
|
@ -18,8 +18,8 @@ class SessionOptionsDialog(Dialog):
|
||||||
self.draw()
|
self.draw()
|
||||||
|
|
||||||
def draw(self):
|
def draw(self):
|
||||||
session_id = self.master.core_grpc.session_id
|
session_id = self.app.core.session_id
|
||||||
response = self.master.core_grpc.core.get_session_options(session_id)
|
response = self.app.core.client.get_session_options(session_id)
|
||||||
logging.info("session options: %s", response)
|
logging.info("session options: %s", response)
|
||||||
self.options = response.config
|
self.options = response.config
|
||||||
self.values = configutils.create_config(self, self.options, PAD_X, PAD_Y)
|
self.values = configutils.create_config(self, self.options, PAD_X, PAD_Y)
|
||||||
|
@ -28,7 +28,7 @@ class SessionOptionsDialog(Dialog):
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
config = configutils.parse_config(self.options, self.values)
|
config = configutils.parse_config(self.options, self.values)
|
||||||
session_id = self.master.core_grpc.session_id
|
session_id = self.app.core.session_id
|
||||||
response = self.master.core_grpc.core.set_session_options(session_id, config)
|
response = self.app.core.client.set_session_options(session_id, config)
|
||||||
logging.info("saved session config: %s", response)
|
logging.info("saved session config: %s", response)
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
|
@ -12,7 +12,7 @@ class SessionsDialog(Dialog):
|
||||||
"""
|
"""
|
||||||
create session table instance
|
create session table instance
|
||||||
|
|
||||||
:param coretk.coregrpc.CoreGrpc grpc: coregrpc
|
:param coretk.coreclient.CoreClient grpc: coregrpc
|
||||||
:param root.master master:
|
:param root.master master:
|
||||||
"""
|
"""
|
||||||
super().__init__(master, app, "Sessions", modal=True)
|
super().__init__(master, app, "Sessions", modal=True)
|
||||||
|
@ -51,7 +51,7 @@ class SessionsDialog(Dialog):
|
||||||
self.tree.column("nodes", stretch=tk.YES)
|
self.tree.column("nodes", stretch=tk.YES)
|
||||||
self.tree.heading("nodes", text="Node Count")
|
self.tree.heading("nodes", text="Node Count")
|
||||||
|
|
||||||
response = self.app.core_grpc.core.get_sessions()
|
response = self.app.core.client.get_sessions()
|
||||||
logging.info("sessions: %s", response)
|
logging.info("sessions: %s", response)
|
||||||
for index, session in enumerate(response.sessions):
|
for index, session in enumerate(response.sessions):
|
||||||
state_name = core_pb2.SessionState.Enum.Name(session.state)
|
state_name = core_pb2.SessionState.Enum.Name(session.state)
|
||||||
|
@ -105,7 +105,7 @@ class SessionsDialog(Dialog):
|
||||||
b.grid(row=0, column=3, padx=2, sticky="ew")
|
b.grid(row=0, column=3, padx=2, sticky="ew")
|
||||||
|
|
||||||
def click_new(self):
|
def click_new(self):
|
||||||
self.app.core_grpc.create_new_session()
|
self.app.core.create_new_session()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
def click_select(self, event):
|
def click_select(self, event):
|
||||||
|
@ -142,10 +142,7 @@ class SessionsDialog(Dialog):
|
||||||
logging.error("querysessiondrawing.py invalid state")
|
logging.error("querysessiondrawing.py invalid state")
|
||||||
|
|
||||||
def join_session(self, session_id):
|
def join_session(self, session_id):
|
||||||
response = self.app.core_grpc.core.get_session(session_id)
|
self.app.core.join_session(session_id)
|
||||||
self.app.core_grpc.session_id = session_id
|
|
||||||
self.app.core_grpc.core.events(session_id, self.app.core_grpc.log_event)
|
|
||||||
logging.info("entering session_id %s.... Result: %s", session_id, response)
|
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
def on_selected(self, event):
|
def on_selected(self, event):
|
||||||
|
@ -154,6 +151,6 @@ class SessionsDialog(Dialog):
|
||||||
self.join_session(sid)
|
self.join_session(sid)
|
||||||
|
|
||||||
def shutdown_session(self, sid):
|
def shutdown_session(self, sid):
|
||||||
self.app.core_grpc.terminate_session(sid)
|
self.app.core.shutdown_session(sid)
|
||||||
self.click_new()
|
self.click_new()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
|
@ -3,14 +3,12 @@ set wallpaper
|
||||||
"""
|
"""
|
||||||
import enum
|
import enum
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import filedialog
|
from tkinter import filedialog
|
||||||
|
|
||||||
from PIL import Image, ImageTk
|
from PIL import Image, ImageTk
|
||||||
|
|
||||||
PATH = os.path.abspath(os.path.dirname(__file__))
|
from coretk.appdirs import BACKGROUNDS_PATH
|
||||||
WALLPAPER_DIR = os.path.join(PATH, "wallpaper")
|
|
||||||
|
|
||||||
|
|
||||||
class ScaleOption(enum.Enum):
|
class ScaleOption(enum.Enum):
|
||||||
|
@ -22,24 +20,24 @@ class ScaleOption(enum.Enum):
|
||||||
|
|
||||||
|
|
||||||
class CanvasWallpaper:
|
class CanvasWallpaper:
|
||||||
def __init__(self, application):
|
def __init__(self, app):
|
||||||
"""
|
"""
|
||||||
create an instance of CanvasWallpaper object
|
create an instance of CanvasWallpaper object
|
||||||
|
|
||||||
:param coretk.app.Application application: root application
|
:param coretk.app.Application app: root application
|
||||||
"""
|
"""
|
||||||
self.application = application
|
self.app = app
|
||||||
self.canvas = self.application.canvas
|
self.canvas = self.app.canvas
|
||||||
|
|
||||||
self.top = tk.Toplevel()
|
self.top = tk.Toplevel()
|
||||||
self.top.title("Set Canvas Wallpaper")
|
self.top.title("Set Canvas Wallpaper")
|
||||||
self.radiovar = tk.IntVar()
|
self.radiovar = tk.IntVar()
|
||||||
print(self.application.radiovar.get())
|
print(self.app.radiovar.get())
|
||||||
self.radiovar.set(self.application.radiovar.get())
|
self.radiovar.set(self.app.radiovar.get())
|
||||||
self.show_grid_var = tk.IntVar()
|
self.show_grid_var = tk.IntVar()
|
||||||
self.show_grid_var.set(self.application.show_grid_var.get())
|
self.show_grid_var.set(self.app.show_grid_var.get())
|
||||||
self.adjust_to_dim_var = tk.IntVar()
|
self.adjust_to_dim_var = tk.IntVar()
|
||||||
self.adjust_to_dim_var.set(self.application.adjust_to_dim_var.get())
|
self.adjust_to_dim_var.set(self.app.adjust_to_dim_var.get())
|
||||||
|
|
||||||
self.create_image_label()
|
self.create_image_label()
|
||||||
self.create_text_label()
|
self.create_text_label()
|
||||||
|
@ -60,7 +58,7 @@ class CanvasWallpaper:
|
||||||
|
|
||||||
def open_image_link(self):
|
def open_image_link(self):
|
||||||
filename = filedialog.askopenfilename(
|
filename = filedialog.askopenfilename(
|
||||||
initialdir=WALLPAPER_DIR,
|
initialdir=str(BACKGROUNDS_PATH),
|
||||||
title="Open",
|
title="Open",
|
||||||
filetypes=(
|
filetypes=(
|
||||||
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
|
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
|
||||||
|
@ -181,7 +179,7 @@ class CanvasWallpaper:
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
canvas = self.application.canvas
|
canvas = self.app.canvas
|
||||||
grid = canvas.find_withtag("rectangle")[0]
|
grid = canvas.find_withtag("rectangle")[0]
|
||||||
x0, y0, x1, y1 = canvas.coords(grid)
|
x0, y0, x1, y1 = canvas.coords(grid)
|
||||||
canvas_w = abs(x0 - x1)
|
canvas_w = abs(x0 - x1)
|
||||||
|
@ -207,7 +205,6 @@ class CanvasWallpaper:
|
||||||
cropy = img_h = tk_img.height()
|
cropy = img_h = tk_img.height()
|
||||||
|
|
||||||
if img_w > canvas_w:
|
if img_w > canvas_w:
|
||||||
|
|
||||||
cropx -= img_w - canvas_w
|
cropx -= img_w - canvas_w
|
||||||
if img_h > canvas_h:
|
if img_h > canvas_h:
|
||||||
cropy -= img_h - canvas_h
|
cropy -= img_h - canvas_h
|
||||||
|
@ -215,7 +212,7 @@ class CanvasWallpaper:
|
||||||
cropped_tk = ImageTk.PhotoImage(cropped)
|
cropped_tk = ImageTk.PhotoImage(cropped)
|
||||||
|
|
||||||
# place left corner of image to the left corner of the canvas
|
# place left corner of image to the left corner of the canvas
|
||||||
self.application.croppedwallpaper = cropped_tk
|
self.app.croppedwallpaper = cropped_tk
|
||||||
|
|
||||||
self.delete_canvas_components(["wallpaper"])
|
self.delete_canvas_components(["wallpaper"])
|
||||||
# self.delete_previous_wallpaper()
|
# self.delete_previous_wallpaper()
|
||||||
|
@ -223,7 +220,7 @@ class CanvasWallpaper:
|
||||||
wid = self.canvas.create_image(
|
wid = self.canvas.create_image(
|
||||||
(cropx / 2, cropy / 2), image=cropped_tk, tags="wallpaper"
|
(cropx / 2, cropy / 2), image=cropped_tk, tags="wallpaper"
|
||||||
)
|
)
|
||||||
self.application.wallpaper_id = wid
|
self.app.wallpaper_id = wid
|
||||||
|
|
||||||
def center(self, img):
|
def center(self, img):
|
||||||
"""
|
"""
|
||||||
|
@ -252,13 +249,13 @@ class CanvasWallpaper:
|
||||||
cropped_tk = ImageTk.PhotoImage(cropped)
|
cropped_tk = ImageTk.PhotoImage(cropped)
|
||||||
|
|
||||||
# place the center of the image at the center of the canvas
|
# place the center of the image at the center of the canvas
|
||||||
self.application.croppedwallpaper = cropped_tk
|
self.app.croppedwallpaper = cropped_tk
|
||||||
self.delete_canvas_components(["wallpaper"])
|
self.delete_canvas_components(["wallpaper"])
|
||||||
# self.delete_previous_wallpaper()
|
# self.delete_previous_wallpaper()
|
||||||
wid = self.canvas.create_image(
|
wid = self.canvas.create_image(
|
||||||
(canvas_w / 2, canvas_h / 2), image=cropped_tk, tags="wallpaper"
|
(canvas_w / 2, canvas_h / 2), image=cropped_tk, tags="wallpaper"
|
||||||
)
|
)
|
||||||
self.application.wallpaper_id = wid
|
self.app.wallpaper_id = wid
|
||||||
|
|
||||||
def scaled(self, img):
|
def scaled(self, img):
|
||||||
"""
|
"""
|
||||||
|
@ -270,7 +267,7 @@ class CanvasWallpaper:
|
||||||
canvas_w, canvas_h = self.get_canvas_width_and_height()
|
canvas_w, canvas_h = self.get_canvas_width_and_height()
|
||||||
resized_image = img.resize((int(canvas_w), int(canvas_h)), Image.ANTIALIAS)
|
resized_image = img.resize((int(canvas_w), int(canvas_h)), Image.ANTIALIAS)
|
||||||
image_tk = ImageTk.PhotoImage(resized_image)
|
image_tk = ImageTk.PhotoImage(resized_image)
|
||||||
self.application.croppedwallpaper = image_tk
|
self.app.croppedwallpaper = image_tk
|
||||||
|
|
||||||
self.delete_canvas_components(["wallpaper"])
|
self.delete_canvas_components(["wallpaper"])
|
||||||
# self.delete_previous_wallpaper()
|
# self.delete_previous_wallpaper()
|
||||||
|
@ -278,7 +275,7 @@ class CanvasWallpaper:
|
||||||
wid = self.canvas.create_image(
|
wid = self.canvas.create_image(
|
||||||
(canvas_w / 2, canvas_h / 2), image=image_tk, tags="wallpaper"
|
(canvas_w / 2, canvas_h / 2), image=image_tk, tags="wallpaper"
|
||||||
)
|
)
|
||||||
self.application.wallpaper_id = wid
|
self.app.wallpaper_id = wid
|
||||||
|
|
||||||
def tiled(self, img):
|
def tiled(self, img):
|
||||||
return
|
return
|
||||||
|
@ -301,15 +298,15 @@ class CanvasWallpaper:
|
||||||
self.delete_canvas_components(["wallpaper"])
|
self.delete_canvas_components(["wallpaper"])
|
||||||
self.draw_new_canvas(img_w, img_h)
|
self.draw_new_canvas(img_w, img_h)
|
||||||
wid = self.canvas.create_image((img_w / 2, img_h / 2), image=image_tk)
|
wid = self.canvas.create_image((img_w / 2, img_h / 2), image=image_tk)
|
||||||
self.application.croppedwallpaper = image_tk
|
self.app.croppedwallpaper = image_tk
|
||||||
self.application.wallpaper_id = wid
|
self.app.wallpaper_id = wid
|
||||||
|
|
||||||
def show_grid(self):
|
def show_grid(self):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.application.adjust_to_dim_var.set(self.adjust_to_dim_var.get())
|
self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get())
|
||||||
|
|
||||||
if self.show_grid_var.get() == 0:
|
if self.show_grid_var.get() == 0:
|
||||||
for i in self.canvas.find_withtag("gridline"):
|
for i in self.canvas.find_withtag("gridline"):
|
||||||
|
@ -322,9 +319,9 @@ class CanvasWallpaper:
|
||||||
logging.error("setwallpaper.py show_grid invalid value")
|
logging.error("setwallpaper.py show_grid invalid value")
|
||||||
|
|
||||||
def save_wallpaper_options(self):
|
def save_wallpaper_options(self):
|
||||||
self.application.radiovar.set(self.radiovar.get())
|
self.app.radiovar.set(self.radiovar.get())
|
||||||
self.application.show_grid_var.set(self.show_grid_var.get())
|
self.app.show_grid_var.set(self.show_grid_var.get())
|
||||||
self.application.adjust_to_dim_var.set(self.adjust_to_dim_var.get())
|
self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get())
|
||||||
|
|
||||||
def click_apply(self):
|
def click_apply(self):
|
||||||
img_link_frame = self.top.grid_slaves(2, 0)[0]
|
img_link_frame = self.top.grid_slaves(2, 0)[0]
|
||||||
|
@ -332,23 +329,23 @@ class CanvasWallpaper:
|
||||||
if not filename:
|
if not filename:
|
||||||
self.delete_canvas_components(["wallpaper"])
|
self.delete_canvas_components(["wallpaper"])
|
||||||
self.top.destroy()
|
self.top.destroy()
|
||||||
self.application.current_wallpaper = None
|
self.app.current_wallpaper = None
|
||||||
self.save_wallpaper_options()
|
self.save_wallpaper_options()
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
img = Image.open(filename)
|
img = Image.open(filename)
|
||||||
self.application.current_wallpaper = img
|
self.app.current_wallpaper = img
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("invalid filename, draw original white plot")
|
print("invalid filename, draw original white plot")
|
||||||
if self.application.wallpaper_id:
|
if self.app.wallpaper_id:
|
||||||
self.canvas.delete(self.application.wallpaper_id)
|
self.canvas.delete(self.app.wallpaper_id)
|
||||||
self.top.destroy()
|
self.top.destroy()
|
||||||
return
|
return
|
||||||
|
|
||||||
self.application.adjust_to_dim_var.set(self.adjust_to_dim_var.get())
|
self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get())
|
||||||
if self.adjust_to_dim_var.get() == 0:
|
if self.adjust_to_dim_var.get() == 0:
|
||||||
|
|
||||||
self.application.radiovar.set(self.radiovar.get())
|
self.app.radiovar.set(self.radiovar.get())
|
||||||
|
|
||||||
if self.radiovar.get() == ScaleOption.UPPER_LEFT.value:
|
if self.radiovar.get() == ScaleOption.UPPER_LEFT.value:
|
||||||
self.upper_left(img)
|
self.upper_left(img)
|
|
@ -4,22 +4,22 @@ size and scale
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from coretk.setwallpaper import ScaleOption
|
from coretk.dialogs.setwallpaper import ScaleOption
|
||||||
|
|
||||||
DRAW_OBJECT_TAGS = ["edge", "node", "nodename", "linkinfo", "antenna"]
|
DRAW_OBJECT_TAGS = ["edge", "node", "nodename", "linkinfo", "antenna"]
|
||||||
|
|
||||||
|
|
||||||
class SizeAndScale:
|
class SizeAndScale:
|
||||||
def __init__(self, application):
|
def __init__(self, app):
|
||||||
"""
|
"""
|
||||||
create an instance for size and scale object
|
create an instance for size and scale object
|
||||||
|
|
||||||
:param application: main application
|
:param app: main application
|
||||||
"""
|
"""
|
||||||
self.application = application
|
self.app = app
|
||||||
self.top = tk.Toplevel()
|
self.top = tk.Toplevel()
|
||||||
self.top.title("Canvas Size and Scale")
|
self.top.title("Canvas Size and Scale")
|
||||||
self.meter_per_pixel = self.application.canvas.meters_per_pixel
|
self.meter_per_pixel = self.app.canvas.meters_per_pixel
|
||||||
|
|
||||||
self.size_chart()
|
self.size_chart()
|
||||||
self.scale_chart()
|
self.scale_chart()
|
||||||
|
@ -108,7 +108,7 @@ class SizeAndScale:
|
||||||
label = tk.Label(self.top, text="Size")
|
label = tk.Label(self.top, text="Size")
|
||||||
label.grid(sticky=tk.W, padx=5)
|
label.grid(sticky=tk.W, padx=5)
|
||||||
|
|
||||||
canvas = self.application.canvas
|
canvas = self.app.canvas
|
||||||
plot = canvas.find_withtag("rectangle")
|
plot = canvas.find_withtag("rectangle")
|
||||||
x0, y0, x1, y1 = canvas.bbox(plot[0])
|
x0, y0, x1, y1 = canvas.bbox(plot[0])
|
||||||
w = abs(x0 - x1) - 2
|
w = abs(x0 - x1) - 2
|
||||||
|
@ -222,7 +222,7 @@ class SizeAndScale:
|
||||||
:param int pixel_height: height in pixel
|
:param int pixel_height: height in pixel
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
canvas = self.application.canvas
|
canvas = self.app.canvas
|
||||||
canvas.config(scrollregion=(0, 0, pixel_width + 200, pixel_height + 200))
|
canvas.config(scrollregion=(0, 0, pixel_width + 200, pixel_height + 200))
|
||||||
|
|
||||||
# delete old plot and redraw
|
# delete old plot and redraw
|
||||||
|
@ -246,24 +246,24 @@ class SizeAndScale:
|
||||||
|
|
||||||
scale_frame = self.top.grid_slaves(3, 0)[0]
|
scale_frame = self.top.grid_slaves(3, 0)[0]
|
||||||
meter_per_pixel = float(scale_frame.grid_slaves(0, 1)[0].get()) / 100
|
meter_per_pixel = float(scale_frame.grid_slaves(0, 1)[0].get()) / 100
|
||||||
self.application.canvas.meters_per_pixel = meter_per_pixel
|
self.app.canvas.meters_per_pixel = meter_per_pixel
|
||||||
self.redraw_grid(pixel_width, pixel_height)
|
self.redraw_grid(pixel_width, pixel_height)
|
||||||
print(self.application.current_wallpaper)
|
print(self.app.current_wallpaper)
|
||||||
print(self.application.radiovar)
|
print(self.app.radiovar)
|
||||||
# if there is a current wallpaper showing, redraw it based on current wallpaper options
|
# if there is a current wallpaper showing, redraw it based on current wallpaper options
|
||||||
wallpaper_tool = self.application.set_wallpaper
|
wallpaper_tool = self.app.set_wallpaper
|
||||||
current_wallpaper = self.application.current_wallpaper
|
current_wallpaper = self.app.current_wallpaper
|
||||||
if current_wallpaper:
|
if current_wallpaper:
|
||||||
if self.application.adjust_to_dim_var.get() == 0:
|
if self.app.adjust_to_dim_var.get() == 0:
|
||||||
if self.application.radiovar.get() == ScaleOption.UPPER_LEFT.value:
|
if self.app.radiovar.get() == ScaleOption.UPPER_LEFT.value:
|
||||||
wallpaper_tool.upper_left(current_wallpaper)
|
wallpaper_tool.upper_left(current_wallpaper)
|
||||||
elif self.application.radiovar.get() == ScaleOption.CENTERED.value:
|
elif self.app.radiovar.get() == ScaleOption.CENTERED.value:
|
||||||
wallpaper_tool.center(current_wallpaper)
|
wallpaper_tool.center(current_wallpaper)
|
||||||
elif self.application.radiovar.get() == ScaleOption.SCALED.value:
|
elif self.app.radiovar.get() == ScaleOption.SCALED.value:
|
||||||
wallpaper_tool.scaled(current_wallpaper)
|
wallpaper_tool.scaled(current_wallpaper)
|
||||||
elif self.application.radiovar.get() == ScaleOption.TILED.value:
|
elif self.app.radiovar.get() == ScaleOption.TILED.value:
|
||||||
print("not implemented")
|
print("not implemented")
|
||||||
elif self.application.adjust_to_dim_var.get() == 1:
|
elif self.app.adjust_to_dim_var.get() == 1:
|
||||||
wallpaper_tool.canvas_to_image_dimension(current_wallpaper)
|
wallpaper_tool.canvas_to_image_dimension(current_wallpaper)
|
||||||
|
|
||||||
wallpaper_tool.show_grid()
|
wallpaper_tool.show_grid()
|
|
@ -6,7 +6,7 @@ import tkinter as tk
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from coretk.dialogs.mobilityconfig import MobilityConfiguration
|
from coretk.dialogs.mobilityconfig import MobilityConfiguration
|
||||||
from coretk.imagemodification import ImageModification
|
from coretk.dialogs.nodeicon import NodeIconDialog
|
||||||
|
|
||||||
|
|
||||||
class WlanConfiguration:
|
class WlanConfiguration:
|
||||||
|
@ -59,16 +59,13 @@ class WlanConfiguration:
|
||||||
e.grid(row=0, column=1, padx=3, pady=3)
|
e.grid(row=0, column=1, padx=3, pady=3)
|
||||||
b = tk.Button(f, text="None")
|
b = tk.Button(f, text="None")
|
||||||
b.grid(row=0, column=2, padx=3, pady=3)
|
b.grid(row=0, column=2, padx=3, pady=3)
|
||||||
b = tk.Button(
|
b = tk.Button(f, image=self.image, command=lambda: self.click_image)
|
||||||
f,
|
|
||||||
image=self.image,
|
|
||||||
command=lambda: ImageModification(
|
|
||||||
canvas=self.canvas, canvas_node=self.canvas_node, node_config=self
|
|
||||||
),
|
|
||||||
)
|
|
||||||
b.grid(row=0, column=3, padx=3, pady=3)
|
b.grid(row=0, column=3, padx=3, pady=3)
|
||||||
f.grid(padx=2, pady=2, ipadx=2, ipady=2)
|
f.grid(padx=2, pady=2, ipadx=2, ipady=2)
|
||||||
|
|
||||||
|
def click_image(self):
|
||||||
|
NodeIconDialog(self.app, canvas_node=self.canvas_node, node_config=self)
|
||||||
|
|
||||||
def create_string_var(self, val):
|
def create_string_var(self, val):
|
||||||
"""
|
"""
|
||||||
create string variable for convenience
|
create string variable for convenience
|
||||||
|
@ -228,9 +225,7 @@ class WlanConfiguration:
|
||||||
f.grid(sticky=tk.W, padx=3, pady=3)
|
f.grid(sticky=tk.W, padx=3, pady=3)
|
||||||
|
|
||||||
def click_ns2_mobility_script(self):
|
def click_ns2_mobility_script(self):
|
||||||
dialog = MobilityConfiguration(
|
dialog = MobilityConfiguration(self.top, self.canvas.core.app, self.canvas_node)
|
||||||
self.top, self.canvas.core_grpc.app, self.canvas_node
|
|
||||||
)
|
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
def wlan_options(self):
|
def wlan_options(self):
|
||||||
|
@ -287,7 +282,7 @@ class WlanConfiguration:
|
||||||
)
|
)
|
||||||
|
|
||||||
# set wireless node configuration here
|
# set wireless node configuration here
|
||||||
wlanconfig_manager = self.canvas.grpc_manager.wlanconfig_management
|
wlanconfig_manager = self.canvas.core.wlanconfig_management
|
||||||
wlanconfig_manager.set_custom_config(
|
wlanconfig_manager.set_custom_config(
|
||||||
node_id=self.canvas_node.core_id,
|
node_id=self.canvas_node.core_id,
|
||||||
range=range_val,
|
range=range_val,
|
|
@ -5,12 +5,10 @@ import tkinter as tk
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
from coretk.canvasaction import CanvasAction
|
from coretk.canvasaction import CanvasAction
|
||||||
from coretk.graph_helper import GraphHelper, WlanAntennaManager
|
from coretk.graph_helper import GraphHelper, WlanAntennaManager
|
||||||
from coretk.grpcmanagement import GrpcManager
|
|
||||||
from coretk.images import Images
|
from coretk.images import Images
|
||||||
from coretk.interface import Interface
|
from coretk.interface import Interface
|
||||||
from coretk.linkinfo import LinkInfo
|
from coretk.linkinfo import LinkInfo, Throughput
|
||||||
|
from coretk.wirelessconnection import WirelessConnection
|
||||||
# from coretk.nodeconfigtable import NodeConfig
|
|
||||||
|
|
||||||
|
|
||||||
class GraphMode(enum.Enum):
|
class GraphMode(enum.Enum):
|
||||||
|
@ -28,7 +26,7 @@ CORE_EMANE = ["emane"]
|
||||||
|
|
||||||
|
|
||||||
class CanvasGraph(tk.Canvas):
|
class CanvasGraph(tk.Canvas):
|
||||||
def __init__(self, master=None, grpc=None, cnf=None, **kwargs):
|
def __init__(self, master, core, cnf=None, **kwargs):
|
||||||
if cnf is None:
|
if cnf is None:
|
||||||
cnf = {}
|
cnf = {}
|
||||||
kwargs["highlightthickness"] = 0
|
kwargs["highlightthickness"] = 0
|
||||||
|
@ -41,22 +39,17 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.nodes = {}
|
self.nodes = {}
|
||||||
self.edges = {}
|
self.edges = {}
|
||||||
self.drawing_edge = None
|
self.drawing_edge = None
|
||||||
|
|
||||||
self.grid = None
|
self.grid = None
|
||||||
self.meters_per_pixel = 1.5
|
self.meters_per_pixel = 1.5
|
||||||
self.canvas_action = CanvasAction(master, self)
|
self.canvas_action = CanvasAction(master, self)
|
||||||
self.setup_menus()
|
self.setup_menus()
|
||||||
self.setup_bindings()
|
self.setup_bindings()
|
||||||
self.draw_grid()
|
self.draw_grid()
|
||||||
|
self.core = core
|
||||||
self.core_grpc = grpc
|
self.helper = GraphHelper(self, core)
|
||||||
self.grpc_manager = GrpcManager(grpc)
|
self.throughput_draw = Throughput(self, core)
|
||||||
|
self.wireless_draw = WirelessConnection(self, core)
|
||||||
self.helper = GraphHelper(self, grpc)
|
|
||||||
self.is_node_context_opened = False
|
self.is_node_context_opened = False
|
||||||
# self.core_id_to_canvas_id = {}
|
|
||||||
# self.core_map = CoreToCanvasMapping()
|
|
||||||
# self.draw_existing_component()
|
|
||||||
|
|
||||||
def setup_menus(self):
|
def setup_menus(self):
|
||||||
self.node_context = tk.Menu(self.master)
|
self.node_context = tk.Menu(self.master)
|
||||||
|
@ -74,14 +67,15 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.node_context.add_command(label="Hide")
|
self.node_context.add_command(label="Hide")
|
||||||
self.node_context.add_command(label="Services")
|
self.node_context.add_command(label="Services")
|
||||||
|
|
||||||
def canvas_reset_and_redraw(self, new_grpc):
|
def canvas_reset_and_redraw(self, session):
|
||||||
"""
|
"""
|
||||||
Reset the private variables CanvasGraph object, redraw nodes given the new grpc client
|
Reset the private variables CanvasGraph object, redraw nodes given the new grpc
|
||||||
:param new_grpc:
|
client.
|
||||||
:return:
|
|
||||||
|
:param core.api.grpc.core_pb2.Session session: session to draw
|
||||||
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
# delete any existing drawn items
|
# delete any existing drawn items
|
||||||
# self.delete_components()
|
|
||||||
self.helper.delete_canvas_components()
|
self.helper.delete_canvas_components()
|
||||||
|
|
||||||
# set the private variables to default value
|
# set the private variables to default value
|
||||||
|
@ -93,12 +87,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
self.nodes.clear()
|
self.nodes.clear()
|
||||||
self.edges.clear()
|
self.edges.clear()
|
||||||
self.drawing_edge = None
|
self.drawing_edge = None
|
||||||
|
self.draw_existing_component(session)
|
||||||
self.grpc_manager = GrpcManager(new_grpc)
|
|
||||||
|
|
||||||
# new grpc
|
|
||||||
self.core_grpc = new_grpc
|
|
||||||
self.draw_existing_component()
|
|
||||||
|
|
||||||
# self.grpc_manager.wlanconfig_management.load_wlan_configurations(self.core_grpc)
|
# self.grpc_manager.wlanconfig_management.load_wlan_configurations(self.core_grpc)
|
||||||
|
|
||||||
|
@ -138,21 +127,17 @@ class CanvasGraph(tk.Canvas):
|
||||||
for i in range(0, height, 27):
|
for i in range(0, height, 27):
|
||||||
self.create_line(0, i, width, i, dash=(2, 4), tags="gridline")
|
self.create_line(0, i, width, i, dash=(2, 4), tags="gridline")
|
||||||
|
|
||||||
def draw_existing_component(self):
|
def draw_existing_component(self, session):
|
||||||
"""
|
"""
|
||||||
Draw existing node and update the information in grpc manager to match
|
Draw existing node and update the information in grpc manager to match
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
core_id_to_canvas_id = {}
|
core_id_to_canvas_id = {}
|
||||||
|
|
||||||
session_id = self.core_grpc.session_id
|
|
||||||
session = self.core_grpc.core.get_session(session_id).session
|
|
||||||
# redraw existing nodes
|
# redraw existing nodes
|
||||||
for node in session.nodes:
|
for node in session.nodes:
|
||||||
# peer to peer node is not drawn on the GUI
|
# peer to peer node is not drawn on the GUI
|
||||||
if node.type != core_pb2.NodeType.PEER_TO_PEER:
|
if node.type != core_pb2.NodeType.PEER_TO_PEER:
|
||||||
|
|
||||||
# draw nodes on the canvas
|
# draw nodes on the canvas
|
||||||
image, name = Images.convert_type_and_model_to_image(
|
image, name = Images.convert_type_and_model_to_image(
|
||||||
node.type, node.model
|
node.type, node.model
|
||||||
|
@ -164,9 +149,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
core_id_to_canvas_id[node.id] = n.id
|
core_id_to_canvas_id[node.id] = n.id
|
||||||
|
|
||||||
# store the node in grpc manager
|
# store the node in grpc manager
|
||||||
self.grpc_manager.add_preexisting_node(n, session_id, node, name)
|
self.core.add_preexisting_node(n, session.id, node, name)
|
||||||
|
|
||||||
self.grpc_manager.update_reusable_id()
|
|
||||||
|
|
||||||
# draw existing links
|
# draw existing links
|
||||||
for link in session.links:
|
for link in session.links:
|
||||||
|
@ -198,7 +181,7 @@ class CanvasGraph(tk.Canvas):
|
||||||
n1.edges.add(e)
|
n1.edges.add(e)
|
||||||
n2.edges.add(e)
|
n2.edges.add(e)
|
||||||
self.edges[e.token] = e
|
self.edges[e.token] = e
|
||||||
self.grpc_manager.add_edge(session_id, e.token, n1.id, n2.id)
|
self.core.add_edge(session.id, e.token, n1.id, n2.id)
|
||||||
|
|
||||||
self.helper.redraw_antenna(link, n1, n2)
|
self.helper.redraw_antenna(link, n1, n2)
|
||||||
|
|
||||||
|
@ -227,14 +210,14 @@ class CanvasGraph(tk.Canvas):
|
||||||
# TODO will include throughput and ipv6 in the future
|
# TODO will include throughput and ipv6 in the future
|
||||||
if1 = Interface(grpc_if1.name, grpc_if1.ip4, ifid=grpc_if1.id)
|
if1 = Interface(grpc_if1.name, grpc_if1.ip4, ifid=grpc_if1.id)
|
||||||
if2 = Interface(grpc_if2.name, grpc_if2.ip4, ifid=grpc_if2.id)
|
if2 = Interface(grpc_if2.name, grpc_if2.ip4, ifid=grpc_if2.id)
|
||||||
self.grpc_manager.edges[e.token].interface_1 = if1
|
self.core.edges[e.token].interface_1 = if1
|
||||||
self.grpc_manager.edges[e.token].interface_2 = if2
|
self.core.edges[e.token].interface_2 = if2
|
||||||
self.grpc_manager.nodes[
|
self.core.nodes[core_id_to_canvas_id[link.node_one_id]].interfaces.append(
|
||||||
core_id_to_canvas_id[link.node_one_id]
|
if1
|
||||||
].interfaces.append(if1)
|
)
|
||||||
self.grpc_manager.nodes[
|
self.core.nodes[core_id_to_canvas_id[link.node_two_id]].interfaces.append(
|
||||||
core_id_to_canvas_id[link.node_two_id]
|
if2
|
||||||
].interfaces.append(if2)
|
)
|
||||||
|
|
||||||
# lift the nodes so they on top of the links
|
# lift the nodes so they on top of the links
|
||||||
for i in self.find_withtag("node"):
|
for i in self.find_withtag("node"):
|
||||||
|
@ -337,13 +320,13 @@ class CanvasGraph(tk.Canvas):
|
||||||
node_dst = self.nodes[edge.dst]
|
node_dst = self.nodes[edge.dst]
|
||||||
node_dst.edges.add(edge)
|
node_dst.edges.add(edge)
|
||||||
|
|
||||||
self.grpc_manager.add_edge(
|
self.core.add_edge(
|
||||||
self.core_grpc.session_id, edge.token, node_src.id, node_dst.id
|
self.core.session_id, edge.token, node_src.id, node_dst.id
|
||||||
)
|
)
|
||||||
|
|
||||||
# draw link info on the edge
|
# draw link info on the edge
|
||||||
if1 = self.grpc_manager.edges[edge.token].interface_1
|
if1 = self.core.edges[edge.token].interface_1
|
||||||
if2 = self.grpc_manager.edges[edge.token].interface_2
|
if2 = self.core.edges[edge.token].interface_2
|
||||||
ip4_and_prefix_1 = None
|
ip4_and_prefix_1 = None
|
||||||
ip4_and_prefix_2 = None
|
ip4_and_prefix_2 = None
|
||||||
if if1 is not None:
|
if if1 is not None:
|
||||||
|
@ -409,12 +392,10 @@ class CanvasGraph(tk.Canvas):
|
||||||
image=image,
|
image=image,
|
||||||
node_type=node_name,
|
node_type=node_name,
|
||||||
canvas=self,
|
canvas=self,
|
||||||
core_id=self.grpc_manager.peek_id(),
|
core_id=self.core.peek_id(),
|
||||||
)
|
)
|
||||||
self.nodes[node.id] = node
|
self.nodes[node.id] = node
|
||||||
self.grpc_manager.add_node(
|
self.core.add_graph_node(self.core.session_id, node.id, x, y, node_name)
|
||||||
self.core_grpc.session_id, node.id, x, y, node_name
|
|
||||||
)
|
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
@ -504,10 +485,10 @@ class CanvasNode:
|
||||||
self.moving = None
|
self.moving = None
|
||||||
|
|
||||||
def double_click(self, event):
|
def double_click(self, event):
|
||||||
node_id = self.canvas.grpc_manager.nodes[self.id].node_id
|
node_id = self.canvas.core.nodes[self.id].node_id
|
||||||
state = self.canvas.core_grpc.get_session_state()
|
state = self.canvas.core.get_session_state()
|
||||||
if state == core_pb2.SessionState.RUNTIME:
|
if state == core_pb2.SessionState.RUNTIME:
|
||||||
self.canvas.core_grpc.launch_terminal(node_id)
|
self.canvas.core.launch_terminal(node_id)
|
||||||
else:
|
else:
|
||||||
self.canvas.canvas_action.display_configuration(self)
|
self.canvas.canvas_action.display_configuration(self)
|
||||||
# if self.node_type in CORE_NODES:
|
# if self.node_type in CORE_NODES:
|
||||||
|
@ -530,9 +511,7 @@ class CanvasNode:
|
||||||
def click_release(self, event):
|
def click_release(self, event):
|
||||||
logging.debug(f"click release {self.name}: {event}")
|
logging.debug(f"click release {self.name}: {event}")
|
||||||
self.update_coords()
|
self.update_coords()
|
||||||
self.canvas.grpc_manager.update_node_location(
|
self.canvas.core.update_node_location(self.id, self.x_coord, self.y_coord)
|
||||||
self.id, self.x_coord, self.y_coord
|
|
||||||
)
|
|
||||||
self.moving = None
|
self.moving = None
|
||||||
|
|
||||||
def motion(self, event):
|
def motion(self, event):
|
||||||
|
@ -550,8 +529,8 @@ class CanvasNode:
|
||||||
|
|
||||||
new_x, new_y = self.canvas.coords(self.id)
|
new_x, new_y = self.canvas.coords(self.id)
|
||||||
|
|
||||||
if self.canvas.core_grpc.get_session_state() == core_pb2.SessionState.RUNTIME:
|
if self.canvas.core.get_session_state() == core_pb2.SessionState.RUNTIME:
|
||||||
self.canvas.core_grpc.edit_node(self.core_id, int(new_x), int(new_y))
|
self.canvas.core.edit_node(self.core_id, int(new_x), int(new_y))
|
||||||
|
|
||||||
for edge in self.edges:
|
for edge in self.edges:
|
||||||
x1, y1, x2, y2 = self.canvas.coords(edge.id)
|
x1, y1, x2, y2 = self.canvas.coords(edge.id)
|
||||||
|
|
|
@ -11,12 +11,12 @@ CANVAS_COMPONENT_TAGS = ["edge", "node", "nodename", "wallpaper", "linkinfo"]
|
||||||
|
|
||||||
|
|
||||||
class GraphHelper:
|
class GraphHelper:
|
||||||
def __init__(self, canvas, grpc):
|
def __init__(self, canvas, core):
|
||||||
"""
|
"""
|
||||||
create an instance of GraphHelper object
|
create an instance of GraphHelper object
|
||||||
"""
|
"""
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.core_grpc = grpc
|
self.core = core
|
||||||
|
|
||||||
def delete_canvas_components(self):
|
def delete_canvas_components(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
"""
|
|
||||||
node image modification
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import tkinter as tk
|
|
||||||
from tkinter import filedialog
|
|
||||||
|
|
||||||
from PIL import Image, ImageTk
|
|
||||||
|
|
||||||
PATH = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
ICONS_DIR = os.path.join(PATH, "icons")
|
|
||||||
|
|
||||||
|
|
||||||
class ImageModification:
|
|
||||||
def __init__(self, canvas, canvas_node, node_config):
|
|
||||||
"""
|
|
||||||
create an instance of ImageModification
|
|
||||||
:param coretk.graph.CanvasGraph canvas: canvas object
|
|
||||||
:param coretk.graph.CanvasNode canvas_node: node object
|
|
||||||
:param coretk.nodeconfigtable.NodeConfig node_config: node configuration object
|
|
||||||
"""
|
|
||||||
self.canvas = canvas
|
|
||||||
self.image = canvas_node.image
|
|
||||||
self.node_type = canvas_node.node_type
|
|
||||||
self.name = canvas_node.name
|
|
||||||
self.canvas_node = canvas_node
|
|
||||||
self.node_configuration = node_config
|
|
||||||
self.p_top = node_config.top
|
|
||||||
|
|
||||||
self.top = tk.Toplevel()
|
|
||||||
self.top.title(self.name + " image")
|
|
||||||
self.image_modification()
|
|
||||||
|
|
||||||
def open_icon_dir(self, toplevel, entry_text):
|
|
||||||
filename = filedialog.askopenfilename(
|
|
||||||
initialdir=ICONS_DIR,
|
|
||||||
title="Open",
|
|
||||||
filetypes=(
|
|
||||||
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
|
|
||||||
("All Files", "*"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if len(filename) > 0:
|
|
||||||
img = Image.open(filename)
|
|
||||||
tk_img = ImageTk.PhotoImage(img)
|
|
||||||
lb = toplevel.grid_slaves(1, 0)[0]
|
|
||||||
lb.configure(image=tk_img)
|
|
||||||
lb.image = tk_img
|
|
||||||
entry_text.set(filename)
|
|
||||||
|
|
||||||
def click_apply(self, toplevel, entry_text):
|
|
||||||
imgfile = entry_text.get()
|
|
||||||
if imgfile:
|
|
||||||
img = Image.open(imgfile)
|
|
||||||
tk_img = ImageTk.PhotoImage(img)
|
|
||||||
f = self.p_top.grid_slaves(row=0, column=0)[0]
|
|
||||||
lb = f.grid_slaves(row=0, column=3)[0]
|
|
||||||
lb.configure(image=tk_img)
|
|
||||||
lb.image = tk_img
|
|
||||||
self.image = tk_img
|
|
||||||
self.node_configuration.image = tk_img
|
|
||||||
toplevel.destroy()
|
|
||||||
|
|
||||||
def image_modification(self):
|
|
||||||
f = tk.Frame(self.top)
|
|
||||||
entry_text = tk.StringVar()
|
|
||||||
image_file_label = tk.Label(f, text="Image file: ")
|
|
||||||
image_file_label.grid(row=0, column=0)
|
|
||||||
image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white")
|
|
||||||
image_file_entry.grid(row=0, column=1)
|
|
||||||
image_file_button = tk.Button(
|
|
||||||
f, text="...", command=lambda: self.open_icon_dir(self.top, entry_text)
|
|
||||||
)
|
|
||||||
image_file_button.grid(row=0, column=2)
|
|
||||||
f.grid()
|
|
||||||
|
|
||||||
img = tk.Label(self.top, image=self.image)
|
|
||||||
img.grid()
|
|
||||||
|
|
||||||
f = tk.Frame(self.top)
|
|
||||||
apply_button = tk.Button(
|
|
||||||
f, text="Apply", command=lambda: self.click_apply(self.top, entry_text)
|
|
||||||
)
|
|
||||||
apply_button.grid(row=0, column=0)
|
|
||||||
apply_to_multiple_button = tk.Button(f, text="Apply to multiple...")
|
|
||||||
apply_to_multiple_button.grid(row=0, column=1)
|
|
||||||
cancel_button = tk.Button(f, text="Cancel", command=self.top.destroy)
|
|
||||||
cancel_button.grid(row=0, column=2)
|
|
||||||
f.grid()
|
|
|
@ -1,23 +1,28 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from PIL import Image, ImageTk
|
from PIL import Image, ImageTk
|
||||||
|
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
|
from coretk.appdirs import LOCAL_ICONS_PATH
|
||||||
PATH = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
ICONS_DIR = os.path.join(PATH, "icons")
|
|
||||||
|
|
||||||
|
|
||||||
class Images:
|
class Images:
|
||||||
images = {}
|
images = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, name, file_path):
|
def create(cls, file_path):
|
||||||
# file_path = os.path.join(PATH, file_path)
|
|
||||||
image = Image.open(file_path)
|
image = Image.open(file_path)
|
||||||
tk_image = ImageTk.PhotoImage(image)
|
return ImageTk.PhotoImage(image)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_all(cls):
|
||||||
|
for image in LOCAL_ICONS_PATH.glob("*"):
|
||||||
|
cls.load(image.stem, str(image))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load(cls, name, file_path):
|
||||||
|
tk_image = cls.create(file_path)
|
||||||
cls.images[name] = tk_image
|
cls.images[name] = tk_image
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -95,10 +100,3 @@ class ImageEnum(Enum):
|
||||||
FILEOPEN = "fileopen"
|
FILEOPEN = "fileopen"
|
||||||
EDITDELETE = "edit-delete"
|
EDITDELETE = "edit-delete"
|
||||||
ANTENNA = "antenna"
|
ANTENNA = "antenna"
|
||||||
|
|
||||||
|
|
||||||
def load_core_images(images):
|
|
||||||
for file_name in os.listdir(ICONS_DIR):
|
|
||||||
file_path = os.path.join(ICONS_DIR, file_name)
|
|
||||||
name = file_name.split(".")[0]
|
|
||||||
images.load(name, file_path)
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ class LinkInfo:
|
||||||
def __init__(self, canvas, edge, ip4_src, ip6_src, ip4_dst, ip6_dst):
|
def __init__(self, canvas, edge, ip4_src, ip6_src, ip4_dst, ip6_dst):
|
||||||
"""
|
"""
|
||||||
create an instance of LinkInfo object
|
create an instance of LinkInfo object
|
||||||
:param tkinter.Canvas canvas: canvas object
|
:param coretk.graph.Graph canvas: canvas object
|
||||||
:param coretk.graph.CanvasEdge edge: canvas edge onject
|
:param coretk.graph.CanvasEdge edge: canvas edge onject
|
||||||
:param ip4_src:
|
:param ip4_src:
|
||||||
:param ip6_src:
|
:param ip6_src:
|
||||||
|
@ -22,7 +22,7 @@ class LinkInfo:
|
||||||
self.edge = edge
|
self.edge = edge
|
||||||
# self.edge_id = edge.id
|
# self.edge_id = edge.id
|
||||||
self.radius = 37
|
self.radius = 37
|
||||||
self.core_grpc = self.canvas.core_grpc
|
self.core = self.canvas.core
|
||||||
|
|
||||||
self.ip4_address_1 = ip4_src
|
self.ip4_address_1 = ip4_src
|
||||||
self.ip6_address_1 = ip6_src
|
self.ip6_address_1 = ip6_src
|
||||||
|
@ -104,29 +104,25 @@ class LinkInfo:
|
||||||
|
|
||||||
|
|
||||||
class Throughput:
|
class Throughput:
|
||||||
def __init__(self, canvas, grpc):
|
def __init__(self, canvas, core):
|
||||||
"""
|
"""
|
||||||
create an instance of Throughput object
|
create an instance of Throughput object
|
||||||
:param tkinter.Canvas canvas: canvas object
|
:param coretk.app.Application app: application
|
||||||
:param coretk.coregrpc,CoreGrpc grpc: grpc object
|
|
||||||
"""
|
"""
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.core_grpc = grpc
|
self.core = core
|
||||||
self.grpc_manager = canvas.grpc_manager
|
|
||||||
|
|
||||||
# edge canvas id mapped to throughput value
|
# edge canvas id mapped to throughput value
|
||||||
self.tracker = {}
|
self.tracker = {}
|
||||||
|
|
||||||
# map an edge canvas id to a throughput canvas id
|
# map an edge canvas id to a throughput canvas id
|
||||||
self.map = {}
|
self.map = {}
|
||||||
|
|
||||||
self.edge_id_to_token = {}
|
self.edge_id_to_token = {}
|
||||||
|
|
||||||
def load_throughput_info(self, interface_throughputs):
|
def load_throughput_info(self, interface_throughputs):
|
||||||
"""
|
"""
|
||||||
load all interface throughouts from an event
|
load all interface throughouts from an event
|
||||||
|
|
||||||
:param repeated core_bp2.InterfaceThroughputinterface_throughputs: interface throughputs
|
:param repeated core_bp2.InterfaceThroughputinterface_throughputs: interface
|
||||||
|
throughputs
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
for t in interface_throughputs:
|
for t in interface_throughputs:
|
||||||
|
@ -134,9 +130,7 @@ class Throughput:
|
||||||
iid = t.interface_id
|
iid = t.interface_id
|
||||||
tp = t.throughput
|
tp = t.throughput
|
||||||
# token = self.grpc_manager.node_id_and_interface_to_edge_token[nid, iid]
|
# token = self.grpc_manager.node_id_and_interface_to_edge_token[nid, iid]
|
||||||
token = self.grpc_manager.core_mapping.get_token_from_node_and_interface(
|
token = self.core.core_mapping.get_token_from_node_and_interface(nid, iid)
|
||||||
nid, iid
|
|
||||||
)
|
|
||||||
print(token)
|
print(token)
|
||||||
edge_id = self.canvas.edges[token].id
|
edge_id = self.canvas.edges[token].id
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,12 @@ import webbrowser
|
||||||
from tkinter import filedialog, messagebox
|
from tkinter import filedialog, messagebox
|
||||||
|
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
|
from coretk.appdirs import XML_PATH
|
||||||
|
from coretk.dialogs.hooks import HooksDialog
|
||||||
from coretk.dialogs.sessionoptions import SessionOptionsDialog
|
from coretk.dialogs.sessionoptions import SessionOptionsDialog
|
||||||
from coretk.dialogs.sessions import SessionsDialog
|
from coretk.dialogs.sessions import SessionsDialog
|
||||||
from coretk.setwallpaper import CanvasWallpaper
|
from coretk.dialogs.setwallpaper import CanvasWallpaper
|
||||||
from coretk.sizeandscale import SizeAndScale
|
from coretk.dialogs.sizeandscale import SizeAndScale
|
||||||
|
|
||||||
SAVEDIR = "/home/ncs/Desktop/"
|
|
||||||
|
|
||||||
|
|
||||||
def sub_menu_items():
|
def sub_menu_items():
|
||||||
|
@ -300,10 +300,6 @@ def session_comments():
|
||||||
logging.debug("Click session comments")
|
logging.debug("Click session comments")
|
||||||
|
|
||||||
|
|
||||||
def session_hooks():
|
|
||||||
logging.debug("Click session hooks")
|
|
||||||
|
|
||||||
|
|
||||||
def session_reset_node_positions():
|
def session_reset_node_positions():
|
||||||
logging.debug("Click session reset node positions")
|
logging.debug("Click session reset node positions")
|
||||||
|
|
||||||
|
@ -321,10 +317,9 @@ class MenuAction:
|
||||||
Actions performed when choosing menu items
|
Actions performed when choosing menu items
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, application, master):
|
def __init__(self, app, master):
|
||||||
self.master = master
|
self.master = master
|
||||||
self.application = application
|
self.app = app
|
||||||
self.core_grpc = application.core_grpc
|
|
||||||
|
|
||||||
def prompt_save_running_session(self):
|
def prompt_save_running_session(self):
|
||||||
"""
|
"""
|
||||||
|
@ -335,27 +330,20 @@ class MenuAction:
|
||||||
logging.info(
|
logging.info(
|
||||||
"menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program"
|
"menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program"
|
||||||
)
|
)
|
||||||
grpc = self.application.core_grpc
|
state = self.app.core.get_session_state()
|
||||||
state = grpc.get_session_state()
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
state == core_pb2.SessionState.SHUTDOWN
|
state == core_pb2.SessionState.SHUTDOWN
|
||||||
or state == core_pb2.SessionState.DEFINITION
|
or state == core_pb2.SessionState.DEFINITION
|
||||||
):
|
):
|
||||||
grpc.delete_session()
|
self.app.core.delete_session()
|
||||||
grpc.core.close()
|
|
||||||
# self.application.quit()
|
|
||||||
else:
|
else:
|
||||||
msgbox = messagebox.askyesnocancel("stop", "Stop the running session?")
|
msgbox = messagebox.askyesnocancel("stop", "Stop the running session?")
|
||||||
|
|
||||||
if msgbox or msgbox is False:
|
if msgbox or msgbox is False:
|
||||||
if msgbox:
|
if msgbox:
|
||||||
grpc.stop_session()
|
self.app.core.stop_session()
|
||||||
grpc.delete_session()
|
self.app.core.delete_session()
|
||||||
# else:
|
|
||||||
# grpc.set_session_state("definition")
|
|
||||||
grpc.core.close()
|
|
||||||
# self.application.quit()
|
|
||||||
|
|
||||||
def on_quit(self):
|
def on_quit(self):
|
||||||
"""
|
"""
|
||||||
|
@ -364,67 +352,41 @@ class MenuAction:
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
self.prompt_save_running_session()
|
self.prompt_save_running_session()
|
||||||
# self.application.core_grpc.close()
|
self.app.quit()
|
||||||
self.application.quit()
|
|
||||||
|
|
||||||
def file_save_as_xml(self):
|
def file_save_as_xml(self):
|
||||||
logging.info("menuaction.py file_save_as_xml()")
|
logging.info("menuaction.py file_save_as_xml()")
|
||||||
grpc = self.application.core_grpc
|
|
||||||
file_path = filedialog.asksaveasfilename(
|
file_path = filedialog.asksaveasfilename(
|
||||||
initialdir=SAVEDIR,
|
initialdir=str(XML_PATH),
|
||||||
title="Save As",
|
title="Save As",
|
||||||
filetypes=(("EmulationScript XML files", "*.xml"), ("All files", "*")),
|
filetypes=(("EmulationScript XML files", "*.xml"), ("All files", "*")),
|
||||||
defaultextension=".xml",
|
defaultextension=".xml",
|
||||||
)
|
)
|
||||||
grpc.save_xml(file_path)
|
if file_path:
|
||||||
|
self.app.core.save_xml(file_path)
|
||||||
|
|
||||||
def file_open_xml(self):
|
def file_open_xml(self):
|
||||||
logging.info("menuaction.py file_open_xml()")
|
logging.info("menuaction.py file_open_xml()")
|
||||||
self.application.is_open_xml = True
|
self.app.is_open_xml = True
|
||||||
file_path = filedialog.askopenfilename(
|
file_path = filedialog.askopenfilename(
|
||||||
initialdir=SAVEDIR,
|
initialdir=str(XML_PATH),
|
||||||
title="Open",
|
title="Open",
|
||||||
filetypes=(("EmulationScript XML File", "*.xml"), ("All Files", "*")),
|
filetypes=(("EmulationScript XML File", "*.xml"), ("All Files", "*")),
|
||||||
)
|
)
|
||||||
# clean up before opening a new session
|
if file_path:
|
||||||
self.prompt_save_running_session()
|
logging.info("opening xml: %s", file_path)
|
||||||
# grpc = CoreGrpc(self.application.master)
|
self.prompt_save_running_session()
|
||||||
# grpc.core.connect()
|
self.app.core.open_xml(file_path)
|
||||||
core_grpc = self.application.core_grpc
|
|
||||||
core_grpc.core.connect()
|
|
||||||
# session_id = core_grpc.open_xml(file_path)
|
|
||||||
# core_grpc.session_id = session_id
|
|
||||||
|
|
||||||
core_grpc.open_xml(file_path)
|
|
||||||
# print("Print session state")
|
|
||||||
# print(grpc.get_session_state())
|
|
||||||
self.application.canvas.canvas_reset_and_redraw(core_grpc)
|
|
||||||
|
|
||||||
self.application.canvas.grpc_manager.wlanconfig_management.load_wlan_configurations(
|
|
||||||
core_grpc
|
|
||||||
)
|
|
||||||
|
|
||||||
self.application.canvas.grpc_manager.mobilityconfig_management.load_mobility_configurations(
|
|
||||||
core_grpc
|
|
||||||
)
|
|
||||||
|
|
||||||
# Todo might not need
|
# Todo might not need
|
||||||
self.application.core_grpc = core_grpc
|
# self.application.core_editbar.destroy_children_widgets()
|
||||||
|
# self.application.core_editbar.create_toolbar()
|
||||||
self.application.core_editbar.destroy_children_widgets()
|
|
||||||
self.application.core_editbar.create_toolbar()
|
|
||||||
# self.application.is_open_xml = False
|
|
||||||
|
|
||||||
# self.application.core_editbar.create_runtime_toolbar()
|
|
||||||
# self.application.canvas.draw_existing_component()
|
|
||||||
# t1 = time.clock()
|
|
||||||
# print(t1 - t0)
|
|
||||||
|
|
||||||
def canvas_size_and_scale(self):
|
def canvas_size_and_scale(self):
|
||||||
self.application.size_and_scale = SizeAndScale(self.application)
|
self.app.size_and_scale = SizeAndScale(self.app)
|
||||||
|
|
||||||
def canvas_set_wallpaper(self):
|
def canvas_set_wallpaper(self):
|
||||||
self.application.set_wallpaper = CanvasWallpaper(self.application)
|
self.app.set_wallpaper = CanvasWallpaper(self.app)
|
||||||
|
|
||||||
def help_core_github(self):
|
def help_core_github(self):
|
||||||
webbrowser.open_new("https://github.com/coreemu/core")
|
webbrowser.open_new("https://github.com/coreemu/core")
|
||||||
|
@ -434,10 +396,15 @@ class MenuAction:
|
||||||
|
|
||||||
def session_options(self):
|
def session_options(self):
|
||||||
logging.debug("Click session options")
|
logging.debug("Click session options")
|
||||||
dialog = SessionOptionsDialog(self.application, self.application)
|
dialog = SessionOptionsDialog(self.app, self.app)
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
def session_change_sessions(self):
|
def session_change_sessions(self):
|
||||||
logging.debug("Click session change sessions")
|
logging.debug("Click session change sessions")
|
||||||
dialog = SessionsDialog(self.application, self.application)
|
dialog = SessionsDialog(self.app, self.app)
|
||||||
|
dialog.show()
|
||||||
|
|
||||||
|
def session_hooks(self):
|
||||||
|
logging.debug("Click session hooks")
|
||||||
|
dialog = HooksDialog(self.app, self.app)
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
|
@ -69,21 +69,3 @@ class MobilityNodeConfig:
|
||||||
self.configurations[node_id]["script_stop"] = script_stop
|
self.configurations[node_id]["script_stop"] = script_stop
|
||||||
else:
|
else:
|
||||||
logging.error("mobilitynodeconfig.py invalid node_id")
|
logging.error("mobilitynodeconfig.py invalid node_id")
|
||||||
|
|
||||||
def load_mobility_configurations(self, core_grpc):
|
|
||||||
"""
|
|
||||||
load mobility configuration from the daemon into memory
|
|
||||||
|
|
||||||
:param coretk.coregrpc.CoreGrpc core_grpc: CoreGrpc object
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
self.configurations.clear()
|
|
||||||
sid = core_grpc.session_id
|
|
||||||
client = core_grpc.core
|
|
||||||
configs = client.get_mobility_configs(sid).configs
|
|
||||||
for nid in configs:
|
|
||||||
node_config = configs[nid].config
|
|
||||||
cnf = OrderedDict()
|
|
||||||
for key in node_config:
|
|
||||||
cnf[key] = node_config[key].value
|
|
||||||
self.configurations[nid] = cnf
|
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
"""
|
|
||||||
Create toplevel for node configuration
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import tkinter as tk
|
|
||||||
from tkinter import filedialog
|
|
||||||
|
|
||||||
from PIL import Image, ImageTk
|
|
||||||
|
|
||||||
from coretk.imagemodification import ImageModification
|
|
||||||
from coretk.nodeservice import NodeServices
|
|
||||||
|
|
||||||
PATH = os.path.abspath(os.path.dirname(__file__))
|
|
||||||
ICONS_DIR = os.path.join(PATH, "icons")
|
|
||||||
|
|
||||||
NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"]
|
|
||||||
DEFAULTNODES = ["router", "host", "PC"]
|
|
||||||
|
|
||||||
|
|
||||||
class NodeConfig:
|
|
||||||
def __init__(self, canvas, canvas_node):
|
|
||||||
"""
|
|
||||||
create an instance of node configuration
|
|
||||||
|
|
||||||
:param coretk.graph.CanvasGraph canvas: canvas object
|
|
||||||
:param coretk.graph.CanvasNode canvas_node: canvas node object
|
|
||||||
"""
|
|
||||||
self.canvas = canvas
|
|
||||||
self.image = canvas_node.image
|
|
||||||
self.node_type = canvas_node.node_type
|
|
||||||
self.name = canvas_node.name
|
|
||||||
self.canvas_node = canvas_node
|
|
||||||
|
|
||||||
self.top = tk.Toplevel()
|
|
||||||
self.top.title(canvas_node.node_type + " configuration")
|
|
||||||
self.namevar = tk.StringVar(self.top, value="default name")
|
|
||||||
self.name_and_image_definition()
|
|
||||||
self.type_and_service_definition()
|
|
||||||
self.select_definition()
|
|
||||||
|
|
||||||
def open_icon_dir(self, toplevel, entry_text):
|
|
||||||
filename = filedialog.askopenfilename(
|
|
||||||
initialdir=ICONS_DIR,
|
|
||||||
title="Open",
|
|
||||||
filetypes=(
|
|
||||||
("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."),
|
|
||||||
("All Files", "*"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if len(filename) > 0:
|
|
||||||
img = Image.open(filename)
|
|
||||||
tk_img = ImageTk.PhotoImage(img)
|
|
||||||
lb = toplevel.grid_slaves(1, 0)[0]
|
|
||||||
lb.configure(image=tk_img)
|
|
||||||
lb.image = tk_img
|
|
||||||
entry_text.set(filename)
|
|
||||||
|
|
||||||
def click_apply(self, toplevel, entry_text):
|
|
||||||
imgfile = entry_text.get()
|
|
||||||
if imgfile:
|
|
||||||
img = Image.open(imgfile)
|
|
||||||
tk_img = ImageTk.PhotoImage(img)
|
|
||||||
lb = self.top.grid_slaves(row=0, column=3)[0]
|
|
||||||
lb.configure(image=tk_img)
|
|
||||||
lb.image = tk_img
|
|
||||||
self.image = tk_img
|
|
||||||
toplevel.destroy()
|
|
||||||
|
|
||||||
def img_modification(self):
|
|
||||||
t = tk.Toplevel()
|
|
||||||
t.title(self.name + " image")
|
|
||||||
|
|
||||||
f = tk.Frame(t)
|
|
||||||
entry_text = tk.StringVar()
|
|
||||||
image_file_label = tk.Label(f, text="Image file: ")
|
|
||||||
image_file_label.grid(row=0, column=0)
|
|
||||||
image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white")
|
|
||||||
image_file_entry.grid(row=0, column=1)
|
|
||||||
image_file_button = tk.Button(
|
|
||||||
f, text="...", command=lambda: self.open_icon_dir(t, entry_text)
|
|
||||||
)
|
|
||||||
image_file_button.grid(row=0, column=2)
|
|
||||||
f.grid()
|
|
||||||
|
|
||||||
img = tk.Label(t, image=self.image)
|
|
||||||
img.grid()
|
|
||||||
|
|
||||||
f = tk.Frame(t)
|
|
||||||
apply_button = tk.Button(
|
|
||||||
f, text="Apply", command=lambda: self.click_apply(t, entry_text)
|
|
||||||
)
|
|
||||||
apply_button.grid(row=0, column=0)
|
|
||||||
apply_to_multiple_button = tk.Button(f, text="Apply to multiple...")
|
|
||||||
apply_to_multiple_button.grid(row=0, column=1)
|
|
||||||
cancel_button = tk.Button(f, text="Cancel", command=t.destroy)
|
|
||||||
cancel_button.grid(row=0, column=2)
|
|
||||||
f.grid()
|
|
||||||
|
|
||||||
def name_and_image_definition(self):
|
|
||||||
f = tk.Frame(self.top, bg="#d9d9d9")
|
|
||||||
name_label = tk.Label(f, text="Node name: ", bg="#d9d9d9")
|
|
||||||
name_label.grid(padx=2, pady=2)
|
|
||||||
name_entry = tk.Entry(f, textvariable=self.namevar)
|
|
||||||
name_entry.grid(row=0, column=1, padx=2, pady=2)
|
|
||||||
|
|
||||||
core_button = tk.Button(f, text="None")
|
|
||||||
core_button.grid(row=0, column=2, padx=2, pady=2)
|
|
||||||
img_button = tk.Button(
|
|
||||||
f,
|
|
||||||
image=self.image,
|
|
||||||
width=40,
|
|
||||||
height=40,
|
|
||||||
command=lambda: ImageModification(self.canvas, self.canvas_node, self),
|
|
||||||
bg="#d9d9d9",
|
|
||||||
)
|
|
||||||
img_button.grid(row=0, column=3, padx=4, pady=4)
|
|
||||||
f.grid(padx=4, pady=4)
|
|
||||||
|
|
||||||
def type_and_service_definition(self):
|
|
||||||
f = tk.Frame(self.top)
|
|
||||||
type_label = tk.Label(f, text="Type: ")
|
|
||||||
type_label.grid(row=0, column=0)
|
|
||||||
|
|
||||||
type_button = tk.Button(f, text="None")
|
|
||||||
type_button.grid(row=0, column=1)
|
|
||||||
|
|
||||||
service_button = tk.Button(
|
|
||||||
f, text="Services...", command=lambda: NodeServices()
|
|
||||||
)
|
|
||||||
service_button.grid(row=0, column=2)
|
|
||||||
|
|
||||||
f.grid(padx=2, pady=2)
|
|
||||||
|
|
||||||
def config_apply(self):
|
|
||||||
"""
|
|
||||||
modify image of the canvas node
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
logging.debug("nodeconfigtable.py configuration apply")
|
|
||||||
self.canvas_node.image = self.image
|
|
||||||
self.canvas_node.canvas.itemconfig(self.canvas_node.id, image=self.image)
|
|
||||||
self.top.destroy()
|
|
||||||
|
|
||||||
def config_cancel(self):
|
|
||||||
"""
|
|
||||||
save chosen image but not modify canvas node
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
logging.debug("nodeconfigtable.py configuration cancel")
|
|
||||||
self.canvas_node.image = self.image
|
|
||||||
self.top.destroy()
|
|
||||||
|
|
||||||
def select_definition(self):
|
|
||||||
f = tk.Frame(self.top)
|
|
||||||
apply_button = tk.Button(f, text="Apply", command=self.config_apply)
|
|
||||||
apply_button.grid(row=0, column=0)
|
|
||||||
cancel_button = tk.Button(f, text="Cancel", command=self.config_cancel)
|
|
||||||
cancel_button.grid(row=0, column=1)
|
|
||||||
f.grid()
|
|
||||||
|
|
||||||
def network_node_config(self):
|
|
||||||
self.name_and_image_definition()
|
|
||||||
self.select_definition()
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB |
|
@ -5,11 +5,9 @@ from core.api.grpc import core_pb2
|
||||||
|
|
||||||
|
|
||||||
class WirelessConnection:
|
class WirelessConnection:
|
||||||
def __init__(self, canvas, grpc):
|
def __init__(self, canvas, core):
|
||||||
self.canvas = canvas
|
self.canvas = canvas
|
||||||
self.core_grpc = grpc
|
self.core_mapping = core.core_mapping
|
||||||
self.core_mapping = canvas.grpc_manager.core_mapping
|
|
||||||
|
|
||||||
# map a (node_one_id, node_two_id) to a wlan canvas id
|
# map a (node_one_id, node_two_id) to a wlan canvas id
|
||||||
self.map = {}
|
self.map = {}
|
||||||
|
|
||||||
|
|
|
@ -35,26 +35,3 @@ class WlanNodeConfig:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
return
|
return
|
||||||
|
|
||||||
def load_wlan_configurations(self, core_grpc):
|
|
||||||
"""
|
|
||||||
load wlan configuration from the daemon
|
|
||||||
|
|
||||||
:param coretk.coregrpc.CoreGrpc core_grpc: CoreGrpc object
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
self.configurations.clear()
|
|
||||||
sid = core_grpc.session_id
|
|
||||||
client = core_grpc.core
|
|
||||||
for node in client.get_session(sid).session.nodes:
|
|
||||||
if node.type == core_pb2.NodeType.WIRELESS_LAN:
|
|
||||||
wlan_config = client.get_wlan_config(sid, node.id).config
|
|
||||||
config = OrderedDict()
|
|
||||||
for key in wlan_config:
|
|
||||||
config[key] = wlan_config[key].value
|
|
||||||
|
|
||||||
# config[key] = wlan_config[key]["value"]
|
|
||||||
# print(config)
|
|
||||||
# for k, v in wlan_config.config:
|
|
||||||
|
|
||||||
self.configurations[node.id] = config
|
|
||||||
|
|
Loading…
Reference in a new issue