pygui some delete node/link cleanup and added unlink option to node context menu for an easier unlinking

This commit is contained in:
Blake Harnden 2020-05-01 23:36:33 -07:00
parent d158fc99c6
commit 5a8984de10
3 changed files with 49 additions and 22 deletions

View file

@ -6,7 +6,7 @@ import logging
import os import os
from pathlib import Path from pathlib import Path
from tkinter import messagebox from tkinter import messagebox
from typing import TYPE_CHECKING, Dict, List from typing import TYPE_CHECKING, Dict, Iterable, List
import grpc import grpc
@ -830,27 +830,21 @@ class CoreClient:
) )
return node return node
def delete_graph_nodes(self, canvas_nodes: List[core_pb2.Node]): def deleted_graph_nodes(self, canvas_nodes: List[core_pb2.Node]):
""" """
remove the nodes selected by the user and anything related to that node remove the nodes selected by the user and anything related to that node
such as link, configurations, interfaces such as link, configurations, interfaces
""" """
edges = set()
removed_links = []
for canvas_node in canvas_nodes: for canvas_node in canvas_nodes:
node_id = canvas_node.core_node.id node_id = canvas_node.core_node.id
if node_id not in self.canvas_nodes:
logging.error("unknown node: %s", node_id)
continue
del self.canvas_nodes[node_id] del self.canvas_nodes[node_id]
for edge in canvas_node.edges:
if edge in edges: def deleted_graph_edges(self, edges: Iterable[CanvasEdge]) -> None:
continue links = []
edges.add(edge) for edge in edges:
edge = self.links.pop(edge.token, None) del self.links[edge.token]
if edge is not None: links.append(edge.link)
removed_links.append(edge.link) self.interfaces_manager.removed(links)
self.interfaces_manager.removed(removed_links)
def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface: def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface:
node = canvas_node.core_node node = canvas_node.core_node

View file

@ -517,15 +517,13 @@ class CanvasGraph(tk.Canvas):
canvas_node.delete() canvas_node.delete()
nodes.append(canvas_node) nodes.append(canvas_node)
is_wireless = NodeUtils.is_wireless_node(canvas_node.core_node.type) is_wireless = NodeUtils.is_wireless_node(canvas_node.core_node.type)
# delete related edges # delete related edges
for edge in canvas_node.edges: for edge in canvas_node.edges:
if edge in edges: if edge in edges:
continue continue
edges.add(edge) edges.add(edge)
self.edges.pop(edge.token, None) del self.edges[edge.token]
edge.delete() edge.delete()
# update node connected to edge being deleted # update node connected to edge being deleted
other_id = edge.src other_id = edge.src
other_interface = edge.src_interface other_interface = edge.src_interface
@ -534,10 +532,8 @@ class CanvasGraph(tk.Canvas):
other_interface = edge.dst_interface other_interface = edge.dst_interface
other_node = self.nodes[other_id] other_node = self.nodes[other_id]
other_node.edges.remove(edge) other_node.edges.remove(edge)
try: if other_interface in other_node.interfaces:
other_node.interfaces.remove(other_interface) other_node.interfaces.remove(other_interface)
except ValueError:
pass
if is_wireless: if is_wireless:
other_node.delete_antenna() other_node.delete_antenna()
@ -547,7 +543,26 @@ class CanvasGraph(tk.Canvas):
shape.delete() shape.delete()
self.selection.clear() self.selection.clear()
self.core.delete_graph_nodes(nodes) self.core.deleted_graph_nodes(nodes)
self.core.deleted_graph_edges(edges)
def delete_edge(self, edge: CanvasEdge):
edge.delete()
del self.edges[edge.token]
src_node = self.nodes[edge.src]
src_node.edges.discard(edge)
if edge.src_interface in src_node.interfaces:
src_node.interfaces.remove(edge.src_interface)
dst_node = self.nodes[edge.dst]
dst_node.edges.discard(edge)
if edge.dst_interface in dst_node.interfaces:
dst_node.interfaces.remove(edge.dst_interface)
src_wireless = NodeUtils.is_wireless_node(src_node.core_node.type)
if src_wireless:
dst_node.delete_antenna()
dst_wireless = NodeUtils.is_wireless_node(dst_node.core_node.type)
if dst_wireless:
src_node.delete_antenna()
def zoom(self, event: tk.Event, factor: float = None): def zoom(self, event: tk.Event, factor: float = None):
if not factor: if not factor:

View file

@ -1,3 +1,4 @@
import functools
import logging import logging
import tkinter as tk import tkinter as tk
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -15,6 +16,7 @@ from core.gui.dialogs.nodeservice import NodeServiceDialog
from core.gui.dialogs.wlanconfig import WlanConfigDialog from core.gui.dialogs.wlanconfig import WlanConfigDialog
from core.gui.errors import show_grpc_error from core.gui.errors import show_grpc_error
from core.gui.graph import tags from core.gui.graph import tags
from core.gui.graph.edges import CanvasEdge
from core.gui.graph.tooltip import CanvasTooltip from core.gui.graph.tooltip import CanvasTooltip
from core.gui.images import ImageEnum, Images from core.gui.images import ImageEnum, Images
from core.gui.nodeutils import ANTENNA_SIZE, NodeUtils from core.gui.nodeutils import ANTENNA_SIZE, NodeUtils
@ -230,6 +232,18 @@ class CanvasNode:
label="Link To Selected", command=self.wireless_link_selected label="Link To Selected", command=self.wireless_link_selected
) )
context.add_command(label="Select Members", state=tk.DISABLED) context.add_command(label="Select Members", state=tk.DISABLED)
unlink_menu = tk.Menu(context)
for edge in self.edges:
other_id = edge.src
if self.id == other_id:
other_id = edge.dst
other_node = self.canvas.nodes[other_id]
func_unlink = functools.partial(self.click_unlink, edge)
unlink_menu.add_command(
label=other_node.core_node.name, command=func_unlink
)
themes.style_menu(unlink_menu)
context.add_cascade(label="Unlink", menu=unlink_menu)
edit_menu = tk.Menu(context) edit_menu = tk.Menu(context)
themes.style_menu(edit_menu) themes.style_menu(edit_menu)
edit_menu.add_command(label="Cut", command=self.click_cut) edit_menu.add_command(label="Cut", command=self.click_cut)
@ -242,6 +256,10 @@ class CanvasNode:
self.canvas_copy() self.canvas_copy()
self.canvas_delete() self.canvas_delete()
def click_unlink(self, edge: CanvasEdge) -> None:
self.canvas.delete_edge(edge)
self.app.core.deleted_graph_edges([edge])
def canvas_delete(self) -> None: def canvas_delete(self) -> None:
self.canvas.clear_selection() self.canvas.clear_selection()
self.canvas.selection[self.id] = self self.canvas.selection[self.id] = self