merged latest from coretk

This commit is contained in:
bharnden 2019-11-07 16:22:34 -08:00
commit be36940bd1
5 changed files with 170 additions and 35 deletions

View file

@ -289,7 +289,6 @@ class CoreClient:
logging.info("delete nodes %s", response) logging.info("delete nodes %s", response)
def delete_links(self, delete_session=None): def delete_links(self, delete_session=None):
# sid = None
if delete_session is None: if delete_session is None:
sid = self.session_id sid = self.session_id
else: else:
@ -312,7 +311,10 @@ class CoreClient:
mobility_configs = self.get_mobility_configs_proto() mobility_configs = self.get_mobility_configs_proto()
emane_model_configs = self.get_emane_model_configs_proto() emane_model_configs = self.get_emane_model_configs_proto()
hooks = list(self.hooks.values()) hooks = list(self.hooks.values())
if self.emane_config:
emane_config = {x: self.emane_config[x].value for x in self.emane_config} emane_config = {x: self.emane_config[x].value for x in self.emane_config}
else:
emane_config = None
response = self.client.start_session( response = self.client.start_session(
self.session_id, self.session_id,
nodes, nodes,
@ -407,23 +409,6 @@ class CoreClient:
else: else:
return self.reusable.pop(0) 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): def add_graph_node(self, session_id, canvas_id, x, y, name):
""" """
Add node, with information filled in, to grpc manager Add node, with information filled in, to grpc manager
@ -478,6 +463,59 @@ class CoreClient:
name, name,
) )
def delete_wanted_graph_nodes(self, canvas_ids, tokens):
"""
remove the nodes selected by the user and anything related to that node
such as link, configurations, interfaces
:param list(int) canvas_ids: list of canvas node ids
:return: nothing
"""
# keep reference to the core ids
core_node_ids = [self.nodes[x].node_id for x in canvas_ids]
node_interface_pairs = []
# delete the nodes
for i in canvas_ids:
try:
n = self.nodes.pop(i)
self.reusable.append(n.node_id)
except KeyError:
logging.error("coreclient.py INVALID NODE CANVAS ID")
self.reusable.sort()
# delete the edges and interfaces
for i in tokens:
try:
e = self.edges.pop(i)
if e.interface_1 is not None:
node_interface_pairs.append(tuple([e.id1, e.interface_1.id]))
if e.interface_2 is not None:
node_interface_pairs.append(tuple([e.id2, e.interface_2.id]))
except KeyError:
logging.error("coreclient.py invalid edge token ")
# delete global emane config if there no longer exist any emane cloud
if core_pb2.NodeType.EMANE not in [x.type for x in self.nodes.values()]:
self.emane_config = None
# delete any mobility configuration, wlan configuration
for i in core_node_ids:
if i in self.mobilityconfig_management.configurations:
self.mobilityconfig_management.configurations.pop(i)
if i in self.wlanconfig_management.configurations:
self.wlanconfig_management.configurations.pop(i)
# delete emane configurations
for i in node_interface_pairs:
if i in self.emaneconfig_management.configurations:
self.emaneconfig_management.configurations.pop(i)
for i in core_node_ids:
if tuple([i, None]) in self.emaneconfig_management.configurations:
self.emaneconfig_management.configurations.pop(tuple([i, None]))
def add_preexisting_node(self, canvas_node, session_id, core_node, name): def add_preexisting_node(self, canvas_node, session_id, core_node, name):
""" """
Add preexisting nodes to grpc manager Add preexisting nodes to grpc manager
@ -531,20 +569,6 @@ class CoreClient:
self.preexisting.clear() self.preexisting.clear()
logging.debug("Next id: %s, Reusable: %s", self.id, self.reusable) 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): def create_interface(self, node_type, gui_interface):
""" """
create a protobuf interface given the interface object stored by the programmer create a protobuf interface given the interface object stored by the programmer

View file

@ -24,7 +24,7 @@ class WlanConfigDialog(Dialog):
self.config = config self.config = config
self.name = tk.StringVar(value=canvas_node.name) self.name = tk.StringVar(value=canvas_node.name)
self.range_var = tk.StringVar(value=config["basic_range"]) self.range_var = tk.StringVar(value=config["range"])
self.bandwidth_var = tk.StringVar(value=config["bandwidth"]) self.bandwidth_var = tk.StringVar(value=config["bandwidth"])
self.delay_var = tk.StringVar(value=config["delay"]) self.delay_var = tk.StringVar(value=config["delay"])
self.loss_var = tk.StringVar(value=config["error"]) self.loss_var = tk.StringVar(value=config["error"])

View file

@ -8,6 +8,7 @@ from coretk.graph_helper import GraphHelper, WlanAntennaManager
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, Throughput from coretk.linkinfo import LinkInfo, Throughput
from coretk.nodedelete import CanvasComponentManagement
from coretk.wirelessconnection import WirelessConnection from coretk.wirelessconnection import WirelessConnection
@ -41,7 +42,11 @@ class CanvasGraph(tk.Canvas):
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_management = CanvasComponentManagement(self, core)
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()
@ -101,6 +106,7 @@ class CanvasGraph(tk.Canvas):
self.bind("<ButtonRelease-1>", self.click_release) self.bind("<ButtonRelease-1>", self.click_release)
self.bind("<B1-Motion>", self.click_motion) self.bind("<B1-Motion>", self.click_motion)
self.bind("<Button-3>", self.context) self.bind("<Button-3>", self.context)
self.bind("<Delete>", self.press_delete)
def draw_grid(self, width=1000, height=800): def draw_grid(self, width=1000, height=800):
""" """
@ -377,6 +383,37 @@ class CanvasGraph(tk.Canvas):
self.node_context.unpost() self.node_context.unpost()
self.is_node_context_opened = False self.is_node_context_opened = False
# TODO rather than delete, might move the data to somewhere else in order to reuse
# TODO when the user undo
def press_delete(self, event):
"""
delete selected nodes and any data that relates to it
:param event:
:return:
"""
# hide nodes, links, link information that shows on the GUI
to_delete_nodes, to_delete_edge_tokens = (
self.canvas_management.delete_selected_nodes()
)
# delete nodes and link info stored in CanvasGraph object
for nid in to_delete_nodes:
self.nodes.pop(nid)
for token in to_delete_edge_tokens:
self.edges.pop(token)
# delete the edge data inside of canvas node
canvas_node_link_to_delete = []
for canvas_id, node in self.nodes.items():
for e in node.edges:
if e.token in to_delete_edge_tokens:
canvas_node_link_to_delete.append(tuple([canvas_id, e]))
for nid, edge in canvas_node_link_to_delete:
self.nodes[nid].edges.remove(edge)
# delete the related data from core
self.core.delete_wanted_graph_nodes(to_delete_nodes, to_delete_edge_tokens)
def add_node(self, x, y, image, node_name): def add_node(self, x, y, image, node_name):
plot_id = self.find_all()[0] plot_id = self.find_all()[0]
logging.info("add node event: %s - %s", plot_id, self.selected) logging.info("add node event: %s - %s", plot_id, self.selected)
@ -474,11 +511,15 @@ class CanvasNode:
self.canvas.tag_bind(self.id, "<B1-Motion>", self.motion) self.canvas.tag_bind(self.id, "<B1-Motion>", self.motion)
self.canvas.tag_bind(self.id, "<Button-3>", self.context) self.canvas.tag_bind(self.id, "<Button-3>", self.context)
self.canvas.tag_bind(self.id, "<Double-Button-1>", self.double_click) self.canvas.tag_bind(self.id, "<Double-Button-1>", self.double_click)
self.canvas.tag_bind(self.id, "<Control-1>", self.select_multiple)
self.edges = set() self.edges = set()
self.wlans = [] self.wlans = []
self.moving = None self.moving = None
def click(self, event):
print("click")
def double_click(self, event): def double_click(self, event):
node_id = self.canvas.core.nodes[self.id].node_id node_id = self.canvas.core.nodes[self.id].node_id
state = self.canvas.core.get_session_state() state = self.canvas.core.get_session_state()
@ -501,7 +542,8 @@ class CanvasNode:
def click_press(self, event): def click_press(self, event):
logging.debug(f"node click press {self.name}: {event}") logging.debug(f"node click press {self.name}: {event}")
self.moving = self.canvas.canvas_xy(event) self.moving = self.canvas.canvas_xy(event)
# return "break"
self.canvas.canvas_management.node_select(self)
def click_release(self, event): def click_release(self, event):
logging.debug(f"node click release {self.name}: {event}") logging.debug(f"node click release {self.name}: {event}")
@ -521,6 +563,7 @@ class CanvasNode:
self.canvas.move(self.id, offset_x, offset_y) self.canvas.move(self.id, offset_x, offset_y)
self.canvas.move(self.text_id, offset_x, offset_y) self.canvas.move(self.text_id, offset_x, offset_y)
self.antenna_draw.update_antennas_position(offset_x, offset_y) self.antenna_draw.update_antennas_position(offset_x, offset_y)
self.canvas.canvas_management.node_drag(self, offset_x, offset_y)
new_x, new_y = self.canvas.coords(self.id) new_x, new_y = self.canvas.coords(self.id)
@ -540,5 +583,8 @@ class CanvasNode:
old_x, old_y, new_x, new_y, self.wlans old_x, old_y, new_x, new_y, self.wlans
) )
def select_multiple(self, event):
self.canvas.canvas_management.node_select(self, True)
def context(self, event): def context(self, event):
logging.debug(f"context click {self.name}: {event}") logging.debug(f"context click {self.name}: {event}")

View file

@ -10,6 +10,10 @@ from core.api.grpc import core_pb2
class MobilityNodeConfig: class MobilityNodeConfig:
def __init__(self): def __init__(self):
"""
create an instance of MobilityConfig object
"""
# dict that maps node id to mobility configuration
self.configurations = {} self.configurations = {}
def set_default_configuration(self, node_type, node_id): def set_default_configuration(self, node_type, node_id):

View file

@ -0,0 +1,61 @@
"""
manage deletion
"""
class CanvasComponentManagement:
def __init__(self, canvas, core):
self.app = core
self.canvas = canvas
# dictionary that maps node to box
self.selected = {}
def node_select(self, canvas_node, choose_multiple=False):
"""
create a bounding box when a node is selected
:param coretk.graph.CanvasNode canvas_node: canvas node object
:return: nothing
"""
if not choose_multiple:
self.delete_current_bbox()
# draw a bounding box if node hasn't been selected yet
if canvas_node.id not in self.selected:
x0, y0, x1, y1 = self.canvas.bbox(canvas_node.id)
bbox_id = self.canvas.create_rectangle(
(x0 - 6, y0 - 6, x1 + 6, y1 + 6), activedash=True, dash="-"
)
self.selected[canvas_node.id] = bbox_id
def node_drag(self, canvas_node, offset_x, offset_y):
self.canvas.move(self.selected[canvas_node.id], offset_x, offset_y)
def delete_current_bbox(self):
for bbid in self.selected.values():
self.canvas.delete(bbid)
self.selected.clear()
def delete_selected_nodes(self):
selected_nodes = list(self.selected.keys())
edges = set()
for n in selected_nodes:
edges = edges.union(self.canvas.nodes[n].edges)
edge_canvas_ids = [x.id for x in edges]
edge_tokens = [x.token for x in edges]
link_infos = [x.link_info.id1 for x in edges] + [x.link_info.id2 for x in edges]
for i in edge_canvas_ids:
self.canvas.itemconfig(i, state="hidden")
for i in link_infos:
self.canvas.itemconfig(i, state="hidden")
for cnid, bbid in self.selected.items():
self.canvas.itemconfig(cnid, state="hidden")
self.canvas.itemconfig(bbid, state="hidden")
self.canvas.itemconfig(self.canvas.nodes[cnid].text_id, state="hidden")
self.selected.clear()
return selected_nodes, edge_tokens