merged latest from coretk and started work on emane configurations

This commit is contained in:
Huy Pham 2019-11-04 15:36:34 -08:00
commit cdb4ed571b
34 changed files with 1330 additions and 740 deletions

View file

@ -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()

View file

@ -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
View 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")

View file

Before

Width:  |  Height:  |  Size: 312 KiB

After

Width:  |  Height:  |  Size: 312 KiB

View file

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

View file

@ -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
View 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")

View file

@ -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):
""" """

View file

@ -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

View file

@ -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):

View file

@ -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
# )

View file

@ -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()

View file

@ -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)

View 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)

View file

@ -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,

View 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()

View 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()

View file

@ -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()

View file

@ -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()

View file

@ -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)

View file

@ -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()

View file

@ -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,

View file

@ -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)

View file

@ -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):
""" """

View file

@ -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()

View file

@ -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)

View file

@ -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

View file

@ -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:
logging.info("opening xml: %s", file_path)
self.prompt_save_running_session() self.prompt_save_running_session()
# grpc = CoreGrpc(self.application.master) self.app.core.open_xml(file_path)
# grpc.core.connect()
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()

View file

@ -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

View file

@ -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

View file

@ -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 = {}

View file

@ -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