commit
daea312162
6 changed files with 63 additions and 26 deletions
|
@ -38,6 +38,17 @@ OBSERVERS = {
|
|||
"IPSec policies": "setkey -DP",
|
||||
}
|
||||
|
||||
DEFAULT_TERMS = {
|
||||
"xterm": "xterm -e",
|
||||
"aterm": "aterm -e",
|
||||
"eterm": "eterm -e",
|
||||
"rxvt": "rxvt -e",
|
||||
"konsole": "konsole -e",
|
||||
"lxterminal": "lxterminal -e",
|
||||
"xfce4-terminal": "xfce4-terminal -x",
|
||||
"gnome-terminal": "gnome-terminal --window--",
|
||||
}
|
||||
|
||||
|
||||
class CoreServer:
|
||||
def __init__(self, name: str, address: str, port: int):
|
||||
|
@ -110,6 +121,8 @@ class CoreClient:
|
|||
self.emane_config = None
|
||||
self.service_configs.clear()
|
||||
self.file_configs.clear()
|
||||
for mobility_player in self.mobility_players.values():
|
||||
mobility_player.handle_close()
|
||||
self.mobility_players.clear()
|
||||
# clear streams
|
||||
if self.handling_throughputs:
|
||||
|
@ -300,6 +313,7 @@ class CoreClient:
|
|||
# get metadata
|
||||
response = self.client.get_session_metadata(self.session_id)
|
||||
self.parse_metadata(response.config)
|
||||
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
|
||||
|
@ -396,7 +410,7 @@ class CoreClient:
|
|||
session_id = self.session_id
|
||||
try:
|
||||
response = self.client.delete_session(session_id)
|
||||
logging.info("deleted session result: %s", response)
|
||||
logging.info("deleted session(%s) result: %s", session_id, response)
|
||||
except grpc.RpcError as e:
|
||||
self.app.after(0, show_grpc_error, e)
|
||||
|
||||
|
@ -527,6 +541,9 @@ class CoreClient:
|
|||
try:
|
||||
terminal = self.app.guiconfig["preferences"]["terminal"]
|
||||
response = self.client.get_node_terminal(self.session_id, node_id)
|
||||
output = os.popen(f"echo {terminal}").read()[:-1]
|
||||
if output in DEFAULT_TERMS:
|
||||
terminal = DEFAULT_TERMS[output]
|
||||
cmd = f'{terminal} "{response.terminal}" &'
|
||||
logging.info("launching terminal %s", cmd)
|
||||
os.system(cmd)
|
||||
|
@ -669,6 +686,8 @@ class CoreClient:
|
|||
config = {x: self.emane_config[x].value for x in self.emane_config}
|
||||
self.client.set_emane_config(self.session_id, config)
|
||||
|
||||
self.set_metadata()
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
Clean ups when done using grpc
|
||||
|
|
|
@ -215,3 +215,7 @@ class SessionsDialog(Dialog):
|
|||
self.tree.delete(item[0])
|
||||
if sid == self.app.core.session_id:
|
||||
self.click_new()
|
||||
selections = self.tree.get_children()
|
||||
if selections:
|
||||
self.tree.focus(selections[0])
|
||||
self.tree.selection_set(selections[0])
|
||||
|
|
|
@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any, Tuple
|
|||
from core.gui import themes
|
||||
from core.gui.dialogs.linkconfig import LinkConfigurationDialog
|
||||
from core.gui.graph import tags
|
||||
from core.gui.nodeutils import NodeUtils
|
||||
from core.gui.nodeutils import EdgeUtils, NodeUtils
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.gui.graph.graph import CanvasGraph
|
||||
|
@ -160,7 +160,7 @@ class CanvasEdge:
|
|||
|
||||
def complete(self, dst: int):
|
||||
self.dst = dst
|
||||
self.token = tuple(sorted((self.src, self.dst)))
|
||||
self.token = EdgeUtils.get_token(self.src, self.dst)
|
||||
x, y = self.canvas.coords(self.dst)
|
||||
x1, y1, _, _ = self.canvas.coords(self.id)
|
||||
self.canvas.coords(self.id, x1, y1, x, y)
|
||||
|
|
|
@ -5,7 +5,6 @@ from typing import TYPE_CHECKING, List, Tuple
|
|||
from PIL import Image, ImageTk
|
||||
|
||||
from core.api.grpc import core_pb2
|
||||
from core.gui import nodeutils
|
||||
from core.gui.dialogs.shapemod import ShapeDialog
|
||||
from core.gui.graph import tags
|
||||
from core.gui.graph.edges import CanvasEdge, CanvasWirelessEdge
|
||||
|
@ -13,8 +12,7 @@ from core.gui.graph.enums import GraphMode, ScaleOption
|
|||
from core.gui.graph.node import CanvasNode
|
||||
from core.gui.graph.shape import Shape
|
||||
from core.gui.graph.shapeutils import ShapeType, is_draw_shape, is_marker
|
||||
from core.gui.images import Images
|
||||
from core.gui.nodeutils import NodeUtils
|
||||
from core.gui.nodeutils import EdgeUtils, NodeUtils
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.gui.app import Application
|
||||
|
@ -192,7 +190,7 @@ class CanvasGraph(tk.Canvas):
|
|||
"""
|
||||
add a wireless edge between 2 canvas nodes
|
||||
"""
|
||||
token = tuple(sorted((src.id, dst.id)))
|
||||
token = EdgeUtils.get_token(src.id, dst.id)
|
||||
x1, y1 = self.coords(src.id)
|
||||
x2, y2 = self.coords(dst.id)
|
||||
position = (x1, y1, x2, y2)
|
||||
|
@ -204,7 +202,7 @@ class CanvasGraph(tk.Canvas):
|
|||
self.tag_raise(dst.id)
|
||||
|
||||
def delete_wireless_edge(self, src: CanvasNode, dst: CanvasNode):
|
||||
token = tuple(sorted((src.id, dst.id)))
|
||||
token = EdgeUtils.get_token(src.id, dst.id)
|
||||
edge = self.wireless_edges.pop(token)
|
||||
edge.delete()
|
||||
src.wireless_edges.remove(edge)
|
||||
|
@ -219,16 +217,7 @@ class CanvasGraph(tk.Canvas):
|
|||
# peer to peer node is not drawn on the GUI
|
||||
if NodeUtils.is_ignore_node(core_node.type):
|
||||
continue
|
||||
|
||||
# draw nodes on the canvas
|
||||
logging.info("drawing core node: %s", core_node)
|
||||
image = NodeUtils.node_icon(core_node.type, core_node.model)
|
||||
if core_node.icon:
|
||||
try:
|
||||
image = Images.create(core_node.icon, nodeutils.ICON_SIZE)
|
||||
except OSError:
|
||||
logging.error("invalid icon: %s", core_node.icon)
|
||||
|
||||
image = NodeUtils.node_image(core_node)
|
||||
x = core_node.position.x
|
||||
y = core_node.position.y
|
||||
node = CanvasNode(self.master, x, y, core_node, image)
|
||||
|
@ -242,7 +231,7 @@ class CanvasGraph(tk.Canvas):
|
|||
node_one = canvas_node_one.core_node
|
||||
canvas_node_two = self.core.canvas_nodes[link.node_two_id]
|
||||
node_two = canvas_node_two.core_node
|
||||
token = tuple(sorted((canvas_node_one.id, canvas_node_two.id)))
|
||||
token = EdgeUtils.get_token(canvas_node_one.id, canvas_node_two.id)
|
||||
|
||||
if link.type == core_pb2.LinkType.WIRELESS:
|
||||
self.add_wireless_edge(canvas_node_one, canvas_node_two)
|
||||
|
@ -266,8 +255,10 @@ class CanvasGraph(tk.Canvas):
|
|||
self.core.links[edge.token] = edge
|
||||
if link.HasField("interface_one"):
|
||||
canvas_node_one.interfaces.append(link.interface_one)
|
||||
edge.src_interface = link.interface_one
|
||||
if link.HasField("interface_two"):
|
||||
canvas_node_two.interfaces.append(link.interface_two)
|
||||
edge.dst_interface = link.interface_two
|
||||
elif link.options.unidirectional:
|
||||
edge = self.edges[token]
|
||||
edge.asymmetric_link = link
|
||||
|
@ -385,7 +376,7 @@ class CanvasGraph(tk.Canvas):
|
|||
return
|
||||
|
||||
# ignore repeated edges
|
||||
token = tuple(sorted((edge.src, self.selected)))
|
||||
token = EdgeUtils.get_token(edge.src, self.selected)
|
||||
if token in self.edges:
|
||||
edge.delete()
|
||||
return
|
||||
|
@ -883,7 +874,7 @@ class CanvasGraph(tk.Canvas):
|
|||
dest_node_copy = self.nodes[copy_map[edge.token[1]]]
|
||||
self.create_edge(source_node_copy, dest_node_copy)
|
||||
copy_edge = self.edges[
|
||||
tuple(sorted([source_node_copy.id, dest_node_copy.id]))
|
||||
EdgeUtils.get_token(source_node_copy.id, dest_node_copy.id)
|
||||
]
|
||||
copy_link = copy_edge.link
|
||||
options = edge.link.options
|
||||
|
|
|
@ -32,10 +32,10 @@ class MenuAction:
|
|||
self.app = app
|
||||
self.canvas = app.canvas
|
||||
|
||||
def cleanup_old_session(self):
|
||||
def cleanup_old_session(self, session_id):
|
||||
logging.info("cleaning up old session")
|
||||
self.app.core.stop_session()
|
||||
self.app.core.delete_session()
|
||||
self.app.core.delete_session(session_id)
|
||||
|
||||
def prompt_save_running_session(self, quitapp: bool = False):
|
||||
"""
|
||||
|
@ -49,7 +49,12 @@ class MenuAction:
|
|||
callback = None
|
||||
if quitapp:
|
||||
callback = self.app.quit
|
||||
task = BackgroundTask(self.app, self.cleanup_old_session, callback)
|
||||
task = BackgroundTask(
|
||||
self.app,
|
||||
self.cleanup_old_session,
|
||||
callback,
|
||||
(self.app.core.session_id,),
|
||||
)
|
||||
task.start()
|
||||
elif quitapp:
|
||||
self.app.quit()
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
from typing import TYPE_CHECKING, Optional, Set
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Optional, Set, Tuple
|
||||
|
||||
from core.api.grpc.core_pb2 import NodeType
|
||||
from core.gui.images import ImageEnum, Images
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from core.api.grpc import core_pb2
|
||||
from PIL import ImageTk
|
||||
|
||||
ICON_SIZE = 48
|
||||
ANTENNA_SIZE = 32
|
||||
|
@ -89,11 +91,21 @@ class NodeUtils:
|
|||
return node_type in cls.RJ45_NODES
|
||||
|
||||
@classmethod
|
||||
def node_icon(cls, node_type: NodeType, model: str) -> bool:
|
||||
def node_icon(cls, node_type: NodeType, model: str) -> "ImageTk.PhotoImage":
|
||||
if model == "":
|
||||
model = None
|
||||
return cls.NODE_ICONS[(node_type, model)]
|
||||
|
||||
@classmethod
|
||||
def node_image(cls, core_node: "core_pb2.Node") -> "ImageTk.PhotoImage":
|
||||
image = cls.node_icon(core_node.type, core_node.model)
|
||||
if core_node.icon:
|
||||
try:
|
||||
image = Images.create(core_node.icon, ICON_SIZE)
|
||||
except OSError:
|
||||
logging.error("invalid icon: %s", core_node.icon)
|
||||
return image
|
||||
|
||||
@classmethod
|
||||
def setup(cls):
|
||||
nodes = [
|
||||
|
@ -123,3 +135,9 @@ class NodeUtils:
|
|||
cls.NETWORK_NODES.append(node_draw)
|
||||
cls.NODE_ICONS[(node_type, None)] = node_draw.image
|
||||
cls.ANTENNA_ICON = Images.get(ImageEnum.ANTENNA, ANTENNA_SIZE)
|
||||
|
||||
|
||||
class EdgeUtils:
|
||||
@classmethod
|
||||
def get_token(cls, src: int, dst: int) -> Tuple[int, ...]:
|
||||
return tuple(sorted([src, dst]))
|
||||
|
|
Loading…
Reference in a new issue