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)
def delete_links(self, delete_session=None):
# sid = None
if delete_session is None:
sid = self.session_id
else:
@ -312,7 +311,10 @@ class CoreClient:
mobility_configs = self.get_mobility_configs_proto()
emane_model_configs = self.get_emane_model_configs_proto()
hooks = list(self.hooks.values())
emane_config = {x: self.emane_config[x].value for x in self.emane_config}
if 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(
self.session_id,
nodes,
@ -407,23 +409,6 @@ class CoreClient:
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
@ -478,6 +463,59 @@ class CoreClient:
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):
"""
Add preexisting nodes to grpc manager
@ -531,20 +569,6 @@ class CoreClient:
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

View file

@ -24,7 +24,7 @@ class WlanConfigDialog(Dialog):
self.config = config
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.delay_var = tk.StringVar(value=config["delay"])
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.interface import Interface
from coretk.linkinfo import LinkInfo, Throughput
from coretk.nodedelete import CanvasComponentManagement
from coretk.wirelessconnection import WirelessConnection
@ -41,7 +42,11 @@ class CanvasGraph(tk.Canvas):
self.drawing_edge = None
self.grid = None
self.meters_per_pixel = 1.5
self.canvas_management = CanvasComponentManagement(self, core)
self.canvas_action = CanvasAction(master, self)
self.setup_menus()
self.setup_bindings()
self.draw_grid()
@ -101,6 +106,7 @@ class CanvasGraph(tk.Canvas):
self.bind("<ButtonRelease-1>", self.click_release)
self.bind("<B1-Motion>", self.click_motion)
self.bind("<Button-3>", self.context)
self.bind("<Delete>", self.press_delete)
def draw_grid(self, width=1000, height=800):
"""
@ -377,6 +383,37 @@ class CanvasGraph(tk.Canvas):
self.node_context.unpost()
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):
plot_id = self.find_all()[0]
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, "<Button-3>", self.context)
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.wlans = []
self.moving = None
def click(self, event):
print("click")
def double_click(self, event):
node_id = self.canvas.core.nodes[self.id].node_id
state = self.canvas.core.get_session_state()
@ -501,7 +542,8 @@ class CanvasNode:
def click_press(self, event):
logging.debug(f"node click press {self.name}: {event}")
self.moving = self.canvas.canvas_xy(event)
# return "break"
self.canvas.canvas_management.node_select(self)
def click_release(self, 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.text_id, 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)
@ -540,5 +583,8 @@ class CanvasNode:
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):
logging.debug(f"context click {self.name}: {event}")

View file

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