From cded9ef63081390d81ed514f8e2365f23fca1fc1 Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Mon, 20 Jan 2020 09:11:43 -0800 Subject: [PATCH 1/5] canvas wallpaper --- daemon/core/gui/coreclient.py | 3 +++ daemon/core/gui/graph/graph.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/daemon/core/gui/coreclient.py b/daemon/core/gui/coreclient.py index f4371715..9427850a 100644 --- a/daemon/core/gui/coreclient.py +++ b/daemon/core/gui/coreclient.py @@ -300,6 +300,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) @@ -669,6 +670,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 diff --git a/daemon/core/gui/graph/graph.py b/daemon/core/gui/graph/graph.py index 76dc427f..707d8bc6 100644 --- a/daemon/core/gui/graph/graph.py +++ b/daemon/core/gui/graph/graph.py @@ -214,6 +214,8 @@ class CanvasGraph(tk.Canvas): """ Draw existing session. """ + print("print session") + print(session) # draw existing nodes for core_node in session.nodes: # peer to peer node is not drawn on the GUI From 510252c4a7ab2cdbb65276fec3637060db0ca1dd Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Mon, 20 Jan 2020 12:04:10 -0800 Subject: [PATCH 2/5] change terminal command --- daemon/core/gui/coreclient.py | 14 ++++++++++++++ daemon/core/gui/graph/graph.py | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/daemon/core/gui/coreclient.py b/daemon/core/gui/coreclient.py index 9427850a..8beffc49 100644 --- a/daemon/core/gui/coreclient.py +++ b/daemon/core/gui/coreclient.py @@ -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): @@ -528,6 +539,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) diff --git a/daemon/core/gui/graph/graph.py b/daemon/core/gui/graph/graph.py index 707d8bc6..40d1fa0f 100644 --- a/daemon/core/gui/graph/graph.py +++ b/daemon/core/gui/graph/graph.py @@ -214,8 +214,6 @@ class CanvasGraph(tk.Canvas): """ Draw existing session. """ - print("print session") - print(session) # draw existing nodes for core_node in session.nodes: # peer to peer node is not drawn on the GUI @@ -268,8 +266,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 From b0087bbde1d60c21869b82c608fc9cd894ea25fe Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Mon, 20 Jan 2020 14:04:31 -0800 Subject: [PATCH 3/5] add nodeutils function to get node's image, add a function to get edge token --- daemon/core/gui/graph/edges.py | 4 ++-- daemon/core/gui/graph/graph.py | 25 +++++++------------------ daemon/core/gui/nodeutils.py | 22 ++++++++++++++++++++-- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/daemon/core/gui/graph/edges.py b/daemon/core/gui/graph/edges.py index 2ca30031..2a198c23 100644 --- a/daemon/core/gui/graph/edges.py +++ b/daemon/core/gui/graph/edges.py @@ -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) diff --git a/daemon/core/gui/graph/graph.py b/daemon/core/gui/graph/graph.py index 40d1fa0f..2b71e7cc 100644 --- a/daemon/core/gui/graph/graph.py +++ b/daemon/core/gui/graph/graph.py @@ -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) @@ -387,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 @@ -885,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 diff --git a/daemon/core/gui/nodeutils.py b/daemon/core/gui/nodeutils.py index 81d4894d..9047174b 100644 --- a/daemon/core/gui/nodeutils.py +++ b/daemon/core/gui/nodeutils.py @@ -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])) From b6f68e0b06a59c19cd13499966c0a1f3503b5dfc Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Mon, 20 Jan 2020 16:01:46 -0800 Subject: [PATCH 4/5] destroy any mobility player dialog before joinning a different session, pass in old_session_id to Menuaction.cleanup_old_session() so that the old session is deleted rather than the new one --- daemon/core/gui/coreclient.py | 4 +++- daemon/core/gui/menuaction.py | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/daemon/core/gui/coreclient.py b/daemon/core/gui/coreclient.py index 8beffc49..e4fd5fac 100644 --- a/daemon/core/gui/coreclient.py +++ b/daemon/core/gui/coreclient.py @@ -121,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: @@ -408,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) diff --git a/daemon/core/gui/menuaction.py b/daemon/core/gui/menuaction.py index 5767d4b1..c9ca355e 100644 --- a/daemon/core/gui/menuaction.py +++ b/daemon/core/gui/menuaction.py @@ -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() From b3463f1fb7314aa4ee62d0499e2e0789d23a21d5 Mon Sep 17 00:00:00 2001 From: Huy Pham <42948410+hpham@users.noreply.github.com> Date: Mon, 20 Jan 2020 16:17:27 -0800 Subject: [PATCH 5/5] set SessionsDialog treeview's current selection again so that deleting multiple sessions is a bit more convenient --- daemon/core/gui/dialogs/sessions.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/daemon/core/gui/dialogs/sessions.py b/daemon/core/gui/dialogs/sessions.py index 6efe598e..3af76c52 100644 --- a/daemon/core/gui/dialogs/sessions.py +++ b/daemon/core/gui/dialogs/sessions.py @@ -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])