From 0e5d7a6f801cf30c6969351a0e3fbec8b0779a56 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 10:45:47 -0700 Subject: [PATCH 01/12] cleanup for organizing how some parameters are passed around, merging logic into central places, avoiding things like needing to requery a session multiple times for joining --- coretk/coretk/app.py | 56 ++++++-------------------- coretk/coretk/appcache.py | 33 --------------- coretk/coretk/coregrpc.py | 50 ++++++++++++++--------- coretk/coretk/coretoolbarhelp.py | 17 ++++---- coretk/coretk/dialogs/sessions.py | 5 +-- coretk/coretk/graph.py | 62 ++++++++++++----------------- coretk/coretk/grpcmanagement.py | 15 +++---- coretk/coretk/images.py | 14 +++---- coretk/coretk/linkinfo.py | 18 ++++----- coretk/coretk/wirelessconnection.py | 3 +- 10 files changed, 100 insertions(+), 173 deletions(-) delete mode 100644 coretk/coretk/appcache.py diff --git a/coretk/coretk/app.py b/coretk/coretk/app.py index f253fd01..bcc43e43 100644 --- a/coretk/coretk/app.py +++ b/coretk/coretk/app.py @@ -1,8 +1,6 @@ import logging import tkinter as tk -import coretk.appcache as appcache -import coretk.images as images from coretk.coregrpc import CoreGrpc from coretk.coremenubar import CoreMenubar from coretk.coretoolbar import CoreToolbar @@ -14,28 +12,25 @@ from coretk.menuaction import MenuAction class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) - appcache.cache_variable(self) - print(self.is_open_xml) - self.load_images() - self.setup_app() + Images.load_all() self.menubar = None self.core_menu = None self.canvas = None self.core_editbar = None - self.core_grpc = None - + self.is_open_xml = False + self.size_and_scale = None + self.set_wallpaper = None + self.wallpaper_id = None + self.current_wallpaper = None + self.radiovar = tk.IntVar(value=1) + self.show_grid_var = tk.IntVar(value=1) + self.adjust_to_dim_var = tk.IntVar(value=0) + self.core_grpc = CoreGrpc(self) + self.setup_app() self.create_menu() self.create_widgets() self.draw_canvas() - self.start_grpc() - # self.try_make_table() - - def load_images(self): - """ - Load core images - :return: - """ - images.load_core_images(Images) + self.core_grpc.set_up() def setup_app(self): self.master.title("CORE") @@ -59,10 +54,7 @@ class Application(tk.Frame): def draw_canvas(self): self.canvas = CanvasGraph( - master=self, - grpc=self.core_grpc, - background="#cccccc", - scrollregion=(0, 0, 1200, 1000), + self, self.core_grpc, background="#cccccc", scrollregion=(0, 0, 1200, 1000) ) self.canvas.pack(fill=tk.BOTH, expand=True) @@ -86,31 +78,9 @@ class Application(tk.Frame): b = tk.Button(status_bar, text="Button 3") b.pack(side=tk.LEFT, padx=1) - def start_grpc(self): - """ - Conect client to grpc, query sessions and prompt use to choose an existing session if there exist any - - :return: nothing - """ - self.master.update() - self.core_grpc = CoreGrpc(self) - self.core_grpc.set_up() - self.canvas.core_grpc = self.core_grpc - self.canvas.grpc_manager.core_grpc = self.core_grpc - self.canvas.grpc_manager.update_preexisting_ids() - self.canvas.draw_existing_component() - def on_closing(self): menu_action = MenuAction(self, self.master) menu_action.on_quit() - # self.quit() - - def try_make_table(self): - f = tk.Frame(self.master) - for i in range(3): - e = tk.Entry(f) - e.grid(row=0, column=1, stick="nsew") - f.pack(side=tk.TOP) if __name__ == "__main__": diff --git a/coretk/coretk/appcache.py b/coretk/coretk/appcache.py deleted file mode 100644 index b2f87f71..00000000 --- a/coretk/coretk/appcache.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -stores some information helpful for setting starting values for some tables -like size and scale, set wallpaper, etc -""" -import tkinter as tk - - -def cache_variable(application): - # for menubar - application.is_open_xml = False - - application.size_and_scale = None - application.set_wallpaper = None - - # set wallpaper variables - - # canvas id of the wallpaper - application.wallpaper_id = None - - # current image for wallpaper - application.current_wallpaper = None - - # wallpaper option - application.radiovar = tk.IntVar() - application.radiovar.set(1) - - # show grid option - application.show_grid_var = tk.IntVar() - application.show_grid_var.set(1) - - # adjust canvas to image dimension variable - application.adjust_to_dim_var = tk.IntVar() - application.adjust_to_dim_var.set(0) diff --git a/coretk/coretk/coregrpc.py b/coretk/coretk/coregrpc.py index 13fe28b3..e38a0940 100644 --- a/coretk/coretk/coregrpc.py +++ b/coretk/coretk/coregrpc.py @@ -7,8 +7,7 @@ from collections import OrderedDict from core.api.grpc import client, core_pb2 from coretk.dialogs.sessions import SessionsDialog -from coretk.linkinfo import Throughput -from coretk.wirelessconnection import WirelessConnection +from coretk.grpcmanagement import GrpcManager class CoreGrpc: @@ -22,15 +21,14 @@ class CoreGrpc: self.app = app self.master = app.master self.interface_helper = None - self.throughput_draw = Throughput(app.canvas, self) - self.wireless_draw = WirelessConnection(app.canvas, self) + self.manager = GrpcManager(self) - def log_event(self, event): + def handle_events(self, event): logging.info("event: %s", event) if event.link_event is not None: - self.wireless_draw.hangle_link_event(event.link_event) + self.app.canvas.wireless_draw.hangle_link_event(event.link_event) - def log_throughput(self, event): + def handle_throughputs(self, event): interface_throughputs = event.interface_throughputs for i in interface_throughputs: print("") @@ -44,6 +42,30 @@ class CoreGrpc: throughputs_belong_to_session ) + def join_session(self, session_id): + # query session and set as current session + self.session_id = session_id + response = self.core.get_session(self.session_id) + logging.info("joining session(%s): %s", self.session_id, response) + self.core.events(self.session_id, self.app.core_grpc.handle_events) + + # determine next node id and reusable nodes + session = response.session + self.manager.reusable.clear() + self.manager.preexisting.clear() + max_id = 1 + for node in session.nodes: + if node.id > max_id: + max_id = node.id + self.manager.preexisting.add(node.id) + self.manager.id = max_id + for i in range(1, self.manager.id): + if i not in self.manager.preexisting: + self.manager.reusable.append(i) + + # draw session + self.app.canvas.draw_existing_component(session) + def create_new_session(self): """ Create a new session @@ -56,7 +78,7 @@ class CoreGrpc: # handle events session may broadcast self.session_id = response.session_id self.master.title("CORE Session ID " + str(self.session_id)) - self.core.events(self.session_id, self.log_event) + self.core.events(self.session_id, self.handle_events) # self.core.throughputs(self.log_throughput) def delete_session(self, custom_sid=None): @@ -114,6 +136,7 @@ class CoreGrpc: else: sid = custom_session_id + response = None if state == "configuration": response = self.core.set_session_state( sid, core_pb2.SessionState.CONFIGURATION @@ -229,15 +252,6 @@ class CoreGrpc: response = self.core.add_link(self.session_id, id1, id2, if1, if2) logging.info("created link: %s", response) - # self.core.get_node_links(self.session_id, id1) - - # def get_session(self): - # response = self.core.get_session(self.session_id) - # nodes = response.session.nodes - # for node in nodes: - # r = self.core.get_node_links(self.session_id, node.id) - # logging.info(r) - def launch_terminal(self, node_id): response = self.core.get_node_terminal(self.session_id, node_id) logging.info("get terminal %s", response.terminal) @@ -252,7 +266,7 @@ class CoreGrpc: """ response = self.core.save_xml(self.session_id, file_path) logging.info("coregrpc.py save xml %s", response) - self.core.events(self.session_id, self.log_event) + self.core.events(self.session_id, self.handle_events) def open_xml(self, file_path): """ diff --git a/coretk/coretk/coretoolbarhelp.py b/coretk/coretk/coretoolbarhelp.py index a02c7ae9..883f293a 100644 --- a/coretk/coretk/coretoolbarhelp.py +++ b/coretk/coretk/coretoolbarhelp.py @@ -4,18 +4,17 @@ CoreToolbar help to draw on canvas, and make grpc client call class CoreToolbarHelp: - def __init__(self, application): - self.application = application - self.core_grpc = application.core_grpc + def __init__(self, app): + self.app = app def add_nodes(self): """ add the nodes stored in grpc manager :return: nothing """ - grpc_manager = self.application.canvas.grpc_manager - for node in grpc_manager.nodes.values(): - self.application.core_grpc.add_node( + manager = self.app.core_grpc.manager + for node in manager.nodes.values(): + self.app.core_grpc.add_node( node.type, node.model, int(node.x), int(node.y), node.name, node.node_id ) @@ -24,8 +23,8 @@ class CoreToolbarHelp: add the edges stored in grpc manager :return: """ - grpc_manager = self.application.canvas.grpc_manager - for edge in grpc_manager.edges.values(): - self.application.core_grpc.add_link( + manager = self.app.core_grpc.manager + for edge in manager.edges.values(): + self.app.core_grpc.add_link( edge.id1, edge.id2, edge.type1, edge.type2, edge ) diff --git a/coretk/coretk/dialogs/sessions.py b/coretk/coretk/dialogs/sessions.py index 10165e2e..b2bd90f0 100644 --- a/coretk/coretk/dialogs/sessions.py +++ b/coretk/coretk/dialogs/sessions.py @@ -142,10 +142,7 @@ class SessionsDialog(Dialog): logging.error("querysessiondrawing.py invalid state") def join_session(self, session_id): - response = self.app.core_grpc.core.get_session(session_id) - self.app.core_grpc.session_id = session_id - self.app.core_grpc.core.events(session_id, self.app.core_grpc.log_event) - logging.info("entering session_id %s.... Result: %s", session_id, response) + self.app.core_grpc.join_session(session_id) self.destroy() def on_selected(self, event): diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 4107401b..e474934f 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -4,11 +4,11 @@ import tkinter as tk from core.api.grpc import core_pb2 from coretk.graph_helper import GraphHelper, WlanAntennaManager -from coretk.grpcmanagement import GrpcManager from coretk.images import Images from coretk.interface import Interface -from coretk.linkinfo import LinkInfo +from coretk.linkinfo import LinkInfo, Throughput from coretk.nodeconfigtable import NodeConfig +from coretk.wirelessconnection import WirelessConnection class GraphMode(enum.Enum): @@ -20,7 +20,7 @@ class GraphMode(enum.Enum): class CanvasGraph(tk.Canvas): - def __init__(self, master=None, grpc=None, cnf=None, **kwargs): + def __init__(self, master, core_grpc, cnf=None, **kwargs): if cnf is None: cnf = {} kwargs["highlightthickness"] = 0 @@ -33,20 +33,15 @@ class CanvasGraph(tk.Canvas): self.nodes = {} self.edges = {} self.drawing_edge = None - self.grid = None self.meters_per_pixel = 1.5 self.setup_menus() self.setup_bindings() self.draw_grid() - - self.core_grpc = grpc - self.grpc_manager = GrpcManager(grpc) - - self.helper = GraphHelper(self, grpc) - # self.core_id_to_canvas_id = {} - # self.core_map = CoreToCanvasMapping() - # self.draw_existing_component() + self.core_grpc = core_grpc + self.helper = GraphHelper(self, core_grpc) + self.throughput_draw = Throughput(self, core_grpc) + self.wireless_draw = WirelessConnection(self, core_grpc) def setup_menus(self): self.node_context = tk.Menu(self.master) @@ -56,7 +51,9 @@ class CanvasGraph(tk.Canvas): def canvas_reset_and_redraw(self, new_grpc): """ - Reset the private variables CanvasGraph object, redraw nodes given the new grpc client + Reset the private variables CanvasGraph object, redraw nodes given the new grpc + client. + :param new_grpc: :return: """ @@ -73,15 +70,11 @@ class CanvasGraph(tk.Canvas): self.nodes = {} self.edges = {} self.drawing_edge = None - - print("graph.py create a new grpc manager") - self.grpc_manager = GrpcManager(new_grpc) - # new grpc self.core_grpc = new_grpc print("grpah.py draw existing component") self.draw_existing_component() - print(self.grpc_manager.edges) + print(self.core_grpc.manager.edges) def setup_bindings(self): """ @@ -119,16 +112,13 @@ class CanvasGraph(tk.Canvas): for i in range(0, height, 27): self.create_line(0, i, width, i, dash=(2, 4), tags="gridline") - def draw_existing_component(self): + def draw_existing_component(self, session): """ Draw existing node and update the information in grpc manager to match :return: nothing """ core_id_to_canvas_id = {} - - session_id = self.core_grpc.session_id - session = self.core_grpc.core.get_session(session_id).session # redraw existing nodes for node in session.nodes: # peer to peer node is not drawn on the GUI @@ -145,9 +135,7 @@ class CanvasGraph(tk.Canvas): core_id_to_canvas_id[node.id] = n.id # store the node in grpc manager - self.grpc_manager.add_preexisting_node(n, session_id, node, name) - - self.grpc_manager.update_reusable_id() + self.core_grpc.manager.add_preexisting_node(n, session.id, node, name) # draw existing links for link in session.links: @@ -179,7 +167,7 @@ class CanvasGraph(tk.Canvas): n1.edges.add(e) n2.edges.add(e) self.edges[e.token] = e - self.grpc_manager.add_edge(session_id, e.token, n1.id, n2.id) + self.core_grpc.manager.add_edge(session.id, e.token, n1.id, n2.id) self.helper.redraw_antenna(link, n1, n2) @@ -208,12 +196,12 @@ class CanvasGraph(tk.Canvas): # TODO will include throughput and ipv6 in the future if1 = Interface(grpc_if1.name, grpc_if1.ip4, ifid=grpc_if1.id) if2 = Interface(grpc_if2.name, grpc_if2.ip4, ifid=grpc_if2.id) - self.grpc_manager.edges[e.token].interface_1 = if1 - self.grpc_manager.edges[e.token].interface_2 = if2 - self.grpc_manager.nodes[ + self.core_grpc.manager.edges[e.token].interface_1 = if1 + self.core_grpc.manager.edges[e.token].interface_2 = if2 + self.core_grpc.manager.nodes[ core_id_to_canvas_id[link.node_one_id] ].interfaces.append(if1) - self.grpc_manager.nodes[ + self.core_grpc.manager.nodes[ core_id_to_canvas_id[link.node_two_id] ].interfaces.append(if2) @@ -316,13 +304,13 @@ class CanvasGraph(tk.Canvas): node_dst = self.nodes[edge.dst] node_dst.edges.add(edge) - self.grpc_manager.add_edge( + self.core_grpc.manager.add_edge( self.core_grpc.session_id, edge.token, node_src.id, node_dst.id ) # draw link info on the edge - if1 = self.grpc_manager.edges[edge.token].interface_1 - if2 = self.grpc_manager.edges[edge.token].interface_2 + if1 = self.core_grpc.manager.edges[edge.token].interface_1 + if2 = self.core_grpc.manager.edges[edge.token].interface_2 ip4_and_prefix_1 = None ip4_and_prefix_2 = None if if1 is not None: @@ -382,10 +370,10 @@ class CanvasGraph(tk.Canvas): image=image, node_type=node_name, canvas=self, - core_id=self.grpc_manager.peek_id(), + core_id=self.core_grpc.manager.peek_id(), ) self.nodes[node.id] = node - self.grpc_manager.add_node( + self.core_grpc.manager.add_node( self.core_grpc.session_id, node.id, x, y, node_name ) return node @@ -477,7 +465,7 @@ class CanvasNode: self.moving = None def double_click(self, event): - node_id = self.canvas.grpc_manager.nodes[self.id].node_id + node_id = self.canvas.core_grpc.manager.nodes[self.id].node_id state = self.canvas.core_grpc.get_session_state() if state == core_pb2.SessionState.RUNTIME: self.canvas.core_grpc.launch_terminal(node_id) @@ -496,7 +484,7 @@ class CanvasNode: def click_release(self, event): logging.debug(f"click release {self.name}: {event}") self.update_coords() - self.canvas.grpc_manager.update_node_location( + self.canvas.core_grpc.manager.update_node_location( self.id, self.x_coord, self.y_coord ) self.moving = None diff --git a/coretk/coretk/grpcmanagement.py b/coretk/coretk/grpcmanagement.py index 9638c7c5..5f10433b 100644 --- a/coretk/coretk/grpcmanagement.py +++ b/coretk/coretk/grpcmanagement.py @@ -57,17 +57,14 @@ class GrpcManager: def __init__(self, grpc): self.nodes = {} self.edges = {} - self.id = None + self.id = 1 # A list of id for re-use, keep in increasing order self.reusable = [] - - self.preexisting = [] - self.core_grpc = None - + self.preexisting = set() + self.core_grpc = grpc # self.update_preexisting_ids() # self.core_id_to_canvas_id = {} self.interfaces_manager = InterfaceManager() - # map tuple(core_node_id, interface_id) to and edge # self.node_id_and_interface_to_edge_token = {} self.core_mapping = CoreToCanvasMapping() @@ -172,7 +169,7 @@ class GrpcManager: print(core_id) if self.id is None or core_id >= self.id: self.id = core_id + 1 - self.preexisting.append(core_id) + self.preexisting.add(core_id) n = Node( session_id, core_id, @@ -219,8 +216,8 @@ class GrpcManager: """ try: self.nodes.pop(canvas_id) - self.reuseable.append(canvas_id) - self.reuseable.sort() + self.reusable.append(canvas_id) + self.reusable.sort() except KeyError: logging.error("grpcmanagement.py INVALID NODE CANVAS ID") diff --git a/coretk/coretk/images.py b/coretk/coretk/images.py index 6a817b6f..241a6997 100644 --- a/coretk/coretk/images.py +++ b/coretk/coretk/images.py @@ -13,6 +13,13 @@ ICONS_DIR = os.path.join(PATH, "icons") class Images: images = {} + @classmethod + def load_all(cls): + for file_name in os.listdir(ICONS_DIR): + file_path = os.path.join(ICONS_DIR, file_name) + name = file_name.split(".")[0] + cls.load(name, file_path) + @classmethod def load(cls, name, file_path): # file_path = os.path.join(PATH, file_path) @@ -91,10 +98,3 @@ class ImageEnum(Enum): FILEOPEN = "fileopen" EDITDELETE = "edit-delete" ANTENNA = "antenna" - - -def load_core_images(images): - for file_name in os.listdir(ICONS_DIR): - file_path = os.path.join(ICONS_DIR, file_name) - name = file_name.split(".")[0] - images.load(name, file_path) diff --git a/coretk/coretk/linkinfo.py b/coretk/coretk/linkinfo.py index c21a56b0..17bc99c8 100644 --- a/coretk/coretk/linkinfo.py +++ b/coretk/coretk/linkinfo.py @@ -11,7 +11,7 @@ class LinkInfo: def __init__(self, canvas, edge, ip4_src, ip6_src, ip4_dst, ip6_dst): """ create an instance of LinkInfo object - :param tkinter.Canvas canvas: canvas object + :param coretk.graph.Graph canvas: canvas object :param coretk.graph.CanvasEdge edge: canvas edge onject :param ip4_src: :param ip6_src: @@ -104,29 +104,25 @@ class LinkInfo: class Throughput: - def __init__(self, canvas, grpc): + def __init__(self, canvas, core_grpc): """ create an instance of Throughput object - :param tkinter.Canvas canvas: canvas object - :param coretk.coregrpc,CoreGrpc grpc: grpc object + :param coretk.app.Application app: application """ self.canvas = canvas - self.core_grpc = grpc - self.grpc_manager = canvas.grpc_manager - + self.core_grpc = core_grpc # edge canvas id mapped to throughput value self.tracker = {} - # map an edge canvas id to a throughput canvas id self.map = {} - self.edge_id_to_token = {} def load_throughput_info(self, interface_throughputs): """ load all interface throughouts from an event - :param repeated core_bp2.InterfaceThroughputinterface_throughputs: interface throughputs + :param repeated core_bp2.InterfaceThroughputinterface_throughputs: interface + throughputs :return: nothing """ for t in interface_throughputs: @@ -134,7 +130,7 @@ class Throughput: iid = t.interface_id tp = t.throughput # token = self.grpc_manager.node_id_and_interface_to_edge_token[nid, iid] - token = self.grpc_manager.core_mapping.get_token_from_node_and_interface( + token = self.core_grpc.manager.core_mapping.get_token_from_node_and_interface( nid, iid ) print(token) diff --git a/coretk/coretk/wirelessconnection.py b/coretk/coretk/wirelessconnection.py index 63042e19..3e4a98f8 100644 --- a/coretk/coretk/wirelessconnection.py +++ b/coretk/coretk/wirelessconnection.py @@ -8,8 +8,7 @@ class WirelessConnection: def __init__(self, canvas, grpc): self.canvas = canvas self.core_grpc = grpc - self.core_mapping = canvas.grpc_manager.core_mapping - + self.core_mapping = grpc.manager.core_mapping # map a (node_one_id, node_two_id) to a wlan canvas id self.map = {} From 1f230146a67df157298088f64f12f89c94dc793d Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 13:15:45 -0700 Subject: [PATCH 02/12] merged grpcmanager with coregrpc --- coretk/coretk/coregrpc.py | 426 ++++++++++++++++++++++------ coretk/coretk/coretocanvas.py | 11 - coretk/coretk/coretoolbarhelp.py | 53 +--- coretk/coretk/graph.py | 28 +- coretk/coretk/grpcmanagement.py | 328 --------------------- coretk/coretk/linkinfo.py | 2 +- coretk/coretk/wirelessconnection.py | 6 +- 7 files changed, 368 insertions(+), 486 deletions(-) delete mode 100644 coretk/coretk/grpcmanagement.py diff --git a/coretk/coretk/coregrpc.py b/coretk/coretk/coregrpc.py index 029a2d16..94f5ca7b 100644 --- a/coretk/coretk/coregrpc.py +++ b/coretk/coretk/coregrpc.py @@ -6,8 +6,54 @@ import os from collections import OrderedDict from core.api.grpc import client, core_pb2 +from coretk.coretocanvas import CoreToCanvasMapping from coretk.dialogs.sessions import SessionsDialog -from coretk.grpcmanagement import GrpcManager +from coretk.interface import Interface, InterfaceManager +from coretk.wlannodeconfig import WlanNodeConfig + +link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"] +network_layer_nodes = ["router", "host", "PC", "mdr", "prouter", "OVS"] + + +class Node: + def __init__(self, session_id, node_id, node_type, model, x, y, name): + """ + Create an instance of a node + + :param int session_id: session id + :param int node_id: node id + :param core_pb2.NodeType node_type: node type + :param int x: x coordinate + :param int y: coordinate + :param str name: node name + """ + self.session_id = session_id + self.node_id = node_id + self.type = node_type + self.x = x + self.y = y + self.model = model + self.name = name + self.interfaces = [] + + +class Edge: + def __init__(self, session_id, node_id_1, node_type_1, node_id_2, node_type_2): + """ + Create an instance of an edge + :param int session_id: session id + :param int node_id_1: node 1 id + :param int node_type_1: node 1 type + :param core_pb2.NodeType node_id_2: node 2 id + :param core_pb2.NodeType node_type_2: node 2 type + """ + self.session_id = session_id + self.id1 = node_id_1 + self.id2 = node_id_2 + self.type1 = node_type_1 + self.type2 = node_type_2 + self.interface_1 = None + self.interface_2 = None class CoreGrpc: @@ -21,7 +67,16 @@ class CoreGrpc: self.app = app self.master = app.master self.interface_helper = None - self.manager = GrpcManager(self) + + # data for managing the current session + self.nodes = {} + self.edges = {} + self.id = 1 + self.reusable = [] + self.preexisting = set() + self.interfaces_manager = InterfaceManager() + self.core_mapping = CoreToCanvasMapping() + self.wlanconfig_management = WlanNodeConfig() def handle_events(self, event): logging.info("event: %s", event) @@ -37,7 +92,6 @@ class CoreGrpc: for if_tp in interface_throughputs: if if_tp.node_id in self.node_ids: throughputs_belong_to_session.append(if_tp) - # bridge_throughputs = event.bridge_throughputs self.throughput_draw.process_grpc_throughput_event( throughputs_belong_to_session ) @@ -47,21 +101,24 @@ class CoreGrpc: self.session_id = session_id response = self.core.get_session(self.session_id) logging.info("joining session(%s): %s", self.session_id, response) - self.core.events(self.session_id, self.app.core_grpc.handle_events) + self.core.events(self.session_id, self.handle_events) + + # set title to session + self.master.title(f"CORE Session({self.session_id})") # determine next node id and reusable nodes session = response.session - self.manager.reusable.clear() - self.manager.preexisting.clear() + self.reusable.clear() + self.preexisting.clear() max_id = 1 for node in session.nodes: if node.id > max_id: max_id = node.id - self.manager.preexisting.add(node.id) - self.manager.id = max_id - for i in range(1, self.manager.id): - if i not in self.manager.preexisting: - self.manager.reusable.append(i) + self.preexisting.add(node.id) + self.id = max_id + for i in range(1, self.id): + if i not in self.preexisting: + self.reusable.append(i) # draw session self.app.canvas.canvas_reset_and_redraw(session) @@ -74,12 +131,7 @@ class CoreGrpc: """ response = self.core.create_session() logging.info("created session: %s", response) - - # handle events session may broadcast - self.session_id = response.session_id - self.master.title("CORE Session ID " + str(self.session_id)) - self.core.events(self.session_id, self.handle_events) - # self.core.throughputs(self.log_throughput) + self.join_session(response.session_id) def delete_session(self, custom_sid=None): if custom_sid is None: @@ -164,28 +216,10 @@ class CoreGrpc: logging.info("set session state: %s", response) - 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.core.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.core.set_wlan_config(self.session_id, node_id, d) - logging.debug("set wlan config %s", r) - return response.node_id - def edit_node(self, node_id, x, y): position = core_pb2.Position(x=x, y=y) response = self.core.edit_node(self.session_id, node_id, position) logging.info("updated node id %s: %s", node_id, response) - # self.core.events(self.session_id, self.log_event) def delete_nodes(self, delete_session=None): if delete_session is None: @@ -213,29 +247,6 @@ class CoreGrpc: ) logging.info("delete links %s", response) - def create_interface(self, node_type, gui_interface): - """ - create a protobuf interface given the interface object stored by the programmer - - :param core_bp2.NodeType type: node type - :param coretk.interface.Interface gui_interface: the programmer's interface object - :rtype: core_bp2.Interface - :return: protobuf interface object - """ - if node_type != core_pb2.NodeType.DEFAULT: - return None - else: - interface = core_pb2.Interface( - id=gui_interface.id, - name=gui_interface.name, - mac=gui_interface.mac, - ip4=gui_interface.ipv4, - ip4mask=gui_interface.ip4prefix, - ) - logging.debug("create interface 1 %s", interface) - - return interface - # TODO add location, hooks, emane_config, etc... def start_session( self, @@ -274,29 +285,6 @@ class CoreGrpc: """ if1 = self.create_interface(type1, edge.interface_1) if2 = self.create_interface(type2, edge.interface_2) - # if type1 == core_pb2.NodeType.DEFAULT: - # interface = edge.interface_1 - # if1 = core_pb2.Interface( - # id=interface.id, - # name=interface.name, - # mac=interface.mac, - # ip4=interface.ipv4, - # ip4mask=interface.ip4prefix, - # ) - # logging.debug("create interface 1 %s", if1) - # # interface1 = self.interface_helper.create_interface(id1, 0) - # - # if type2 == core_pb2.NodeType.DEFAULT: - # interface = edge.interface_2 - # if2 = core_pb2.Interface( - # id=interface.id, - # name=interface.name, - # mac=interface.mac, - # ip4=interface.ipv4, - # ip4mask=interface.ip4prefix, - # ) - # logging.debug("create interface 2: %s", if2) - response = self.core.add_link(self.session_id, id1, id2, if1, if2) logging.info("created link: %s", response) @@ -335,3 +323,279 @@ class CoreGrpc: """ logging.debug("Close grpc") self.core.close() + + def peek_id(self): + """ + Peek the next id to be used + + :return: nothing + """ + if len(self.reusable) == 0: + return self.id + else: + return self.reusable[0] + + def get_id(self): + """ + Get the next node id as well as update id status and reusable ids + + :rtype: int + :return: the next id to be used + """ + if len(self.reusable) == 0: + new_id = self.id + self.id = self.id + 1 + return new_id + 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.core.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.core.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 + + :param int session_id: session id + :param int canvas_id: node's canvas id + :param int x: x coord + :param int y: y coord + :param str name: node type + :return: nothing + """ + node_type = None + node_model = None + if name in link_layer_nodes: + if name == "switch": + node_type = core_pb2.NodeType.SWITCH + elif name == "hub": + node_type = core_pb2.NodeType.HUB + elif name == "wlan": + node_type = core_pb2.NodeType.WIRELESS_LAN + elif name == "rj45": + node_type = core_pb2.NodeType.RJ45 + elif name == "tunnel": + node_type = core_pb2.NodeType.TUNNEL + elif name in network_layer_nodes: + node_type = core_pb2.NodeType.DEFAULT + node_model = name + else: + logging.error("grpcmanagemeny.py INVALID node name") + nid = self.get_id() + create_node = Node(session_id, nid, node_type, node_model, x, y, name) + + # set default configuration for wireless node + self.wlanconfig_management.set_default_config(node_type, nid) + + self.nodes[canvas_id] = create_node + self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id) + # self.core_id_to_canvas_id[nid] = canvas_id + logging.debug( + "Adding node to GrpcManager.. Session id: %s, Coords: (%s, %s), Name: %s", + session_id, + x, + y, + name, + ) + + def add_preexisting_node(self, canvas_node, session_id, core_node, name): + """ + Add preexisting nodes to grpc manager + + :param str name: node_type + :param core_pb2.Node core_node: core node grpc message + :param coretk.graph.CanvasNode canvas_node: canvas node + :param int session_id: session id + :return: nothing + """ + + # update the next available id + core_id = core_node.id + if self.id is None or core_id >= self.id: + self.id = core_id + 1 + self.preexisting.add(core_id) + n = Node( + session_id, + core_id, + core_node.type, + core_node.model, + canvas_node.x_coord, + canvas_node.y_coord, + name, + ) + self.nodes[canvas_node.id] = n + + def update_node_location(self, canvas_id, new_x, new_y): + """ + update node + + :param int canvas_id: canvas id of that node + :param int new_x: new x coord + :param int new_y: new y coord + :return: nothing + """ + self.nodes[canvas_id].x = new_x + self.nodes[canvas_id].y = new_y + + def update_reusable_id(self): + """ + Update available id for reuse + + :return: nothing + """ + if len(self.preexisting) > 0: + for i in range(1, self.id): + if i not in self.preexisting: + self.reusable.append(i) + + 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 + + :param core_bp2.NodeType type: node type + :param coretk.interface.Interface gui_interface: the programmer's interface object + :rtype: core_bp2.Interface + :return: protobuf interface object + """ + if node_type != core_pb2.NodeType.DEFAULT: + return None + else: + interface = core_pb2.Interface( + id=gui_interface.id, + name=gui_interface.name, + mac=gui_interface.mac, + ip4=gui_interface.ipv4, + ip4mask=gui_interface.ip4prefix, + ) + logging.debug("create interface: %s", interface) + return interface + + def create_edge_interface(self, edge, src_canvas_id, dst_canvas_id): + """ + Create the interface for the two end of an edge, add a copy to node's interfaces + + :param coretk.grpcmanagement.Edge edge: edge to add interfaces to + :param int src_canvas_id: canvas id for the source node + :param int dst_canvas_id: canvas id for the destination node + :return: nothing + """ + src_interface = None + dst_interface = None + print("create interface") + self.interfaces_manager.new_subnet() + + src_node = self.nodes[src_canvas_id] + if src_node.model in network_layer_nodes: + ifid = len(src_node.interfaces) + name = "eth" + str(ifid) + src_interface = Interface( + name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address()) + ) + self.nodes[src_canvas_id].interfaces.append(src_interface) + logging.debug( + "Create source interface 1... IP: %s, name: %s", + src_interface.ipv4, + src_interface.name, + ) + + dst_node = self.nodes[dst_canvas_id] + if dst_node.model in network_layer_nodes: + ifid = len(dst_node.interfaces) + name = "eth" + str(ifid) + dst_interface = Interface( + name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address()) + ) + self.nodes[dst_canvas_id].interfaces.append(dst_interface) + logging.debug( + "Create destination interface... IP: %s, name: %s", + dst_interface.ipv4, + dst_interface.name, + ) + + edge.interface_1 = src_interface + edge.interface_2 = dst_interface + return src_interface, dst_interface + + def add_edge(self, session_id, token, canvas_id_1, canvas_id_2): + """ + Add an edge to grpc manager + + :param int session_id: core session id + :param tuple(int, int) token: edge's identification in the canvas + :param int canvas_id_1: canvas id of source node + :param int canvas_id_2: canvas_id of destination node + + :return: nothing + """ + if canvas_id_1 in self.nodes and canvas_id_2 in self.nodes: + edge = Edge( + session_id, + self.nodes[canvas_id_1].node_id, + self.nodes[canvas_id_1].type, + self.nodes[canvas_id_2].node_id, + self.nodes[canvas_id_2].type, + ) + self.edges[token] = edge + src_interface, dst_interface = self.create_edge_interface( + edge, canvas_id_1, canvas_id_2 + ) + node_one_id = self.nodes[canvas_id_1].node_id + node_two_id = self.nodes[canvas_id_2].node_id + + # provide a way to get an edge from a core node and an interface id + if src_interface is not None: + self.core_mapping.map_node_and_interface_to_canvas_edge( + node_one_id, src_interface.id, token + ) + logging.debug( + "map node id %s, interface_id %s to edge token %s", + node_one_id, + src_interface.id, + token, + ) + + if dst_interface is not None: + self.core_mapping.map_node_and_interface_to_canvas_edge( + node_two_id, dst_interface.id, token + ) + logging.debug( + "map node id %s, interface_id %s to edge token %s", + node_two_id, + dst_interface.id, + token, + ) + + logging.debug("Adding edge to grpc manager...") + else: + logging.error("grpcmanagement.py INVALID CANVAS NODE ID") diff --git a/coretk/coretk/coretocanvas.py b/coretk/coretk/coretocanvas.py index e808735f..6e767db3 100644 --- a/coretk/coretk/coretocanvas.py +++ b/coretk/coretk/coretocanvas.py @@ -8,7 +8,6 @@ class CoreToCanvasMapping: def __init__(self): self.core_id_to_canvas_id = {} self.core_node_and_interface_to_canvas_edge = {} - # self.edge_id_to_canvas_token = {} def map_node_and_interface_to_canvas_edge(self, nid, iid, edge_token): self.core_node_and_interface_to_canvas_edge[tuple([nid, iid])] = edge_token @@ -33,13 +32,3 @@ class CoreToCanvasMapping: else: logging.debug("invalid key") return None - - # def add_mapping(self, core_id, canvas_id): - # if core_id not in self.core_id_to_canvas_id: - # self.core_id_to_canvas_id[core_id] = canvas_id - # else: - # logging.error("key already mapped") - # - # def delete_mapping(self, core_id): - # result = self.core_id_to_canvas_id.pop(core_id, None) - # return result diff --git a/coretk/coretk/coretoolbarhelp.py b/coretk/coretk/coretoolbarhelp.py index 3a0b8623..b26269db 100644 --- a/coretk/coretk/coretoolbarhelp.py +++ b/coretk/coretk/coretoolbarhelp.py @@ -15,8 +15,8 @@ class CoreToolbarHelp: :return: nothing """ nodes = [] - manager = self.app.core_grpc.manager - for node in manager.nodes.values(): + core = self.app.core_grpc + for node in core.nodes.values(): pos = core_pb2.Position(x=int(node.x), y=int(node.y)) n = core_pb2.Node( id=node.node_id, type=node.type, position=pos, model=node.model @@ -32,8 +32,8 @@ class CoreToolbarHelp: :return: list of protobuf links """ links = [] - manager = self.app.core_grpc.manager - for edge in manager.edges.values(): + core = self.app.core_grpc + for edge in core.edges.values(): interface_one = self.app.core_grpc.create_interface( edge.type1, edge.interface_1 ) @@ -56,61 +56,20 @@ class CoreToolbarHelp: interface_two=interface_two, ) links.append(link) - # self.id1 = edge.id1 - # self.id2 = edge.id2 - # self.type = link_type - # self.if1 = interface_one - # self.if2 = interface_two return links def get_wlan_configuration_list(self): configs = [] - manager = self.app.core_grpc.manager - manager_configs = manager.wlanconfig_management.configurations + core = self.app.core_grpc + manager_configs = core.wlanconfig_management.configurations for key in manager_configs: cnf = core_pb2.WlanConfig(node_id=key, config=manager_configs[key]) configs.append(cnf) return configs def gui_start_session(self): - # list(core_pb2.Node) nodes = self.get_node_list() - - # list(core_bp2.Link) links = self.get_link_list() - - # print(links[0]) wlan_configs = self.get_wlan_configuration_list() - # print(wlan_configs) self.app.core_grpc.start_session(nodes, links, wlan_configs=wlan_configs) - # self.core_grpc.core.add_link(self.core_grpc.session_id, self.id1, self.id2, self.if1, self.if2) - # res = self.core_grpc.core.get_wlan_config(self.core_grpc.session_id, 1) - - # res = self.core_grpc.core.get_session(self.core_grpc.session_id).session - # print(res) - # res = self.core_grpc.core.get_wlan_config(self.core_grpc.session_id, 1) - - # print(res) - - # def add_nodes(self): - # """ - # add the nodes stored in grpc manager - # :return: nothing - # """ - # grpc_manager = self.application.canvas.grpc_manager - # for node in grpc_manager.nodes.values(): - # self.application.core_grpc.add_node( - # node.type, node.model, int(node.x), int(node.y), node.name, node.node_id - # ) - # - # def add_edges(self): - # """ - # add the edges stored in grpc manager - # :return: - # """ - # grpc_manager = self.application.canvas.grpc_manager - # for edge in grpc_manager.edges.values(): - # self.application.core_grpc.add_link( - # edge.id1, edge.id2, edge.type1, edge.type2, edge - # ) diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 5b76cdcb..7859a8e6 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -147,7 +147,7 @@ class CanvasGraph(tk.Canvas): core_id_to_canvas_id[node.id] = n.id # store the node in grpc manager - self.core_grpc.manager.add_preexisting_node(n, session.id, node, name) + self.core_grpc.add_preexisting_node(n, session.id, node, name) # draw existing links for link in session.links: @@ -179,7 +179,7 @@ class CanvasGraph(tk.Canvas): n1.edges.add(e) n2.edges.add(e) self.edges[e.token] = e - self.core_grpc.manager.add_edge(session.id, e.token, n1.id, n2.id) + self.core_grpc.add_edge(session.id, e.token, n1.id, n2.id) self.helper.redraw_antenna(link, n1, n2) @@ -208,12 +208,12 @@ class CanvasGraph(tk.Canvas): # TODO will include throughput and ipv6 in the future if1 = Interface(grpc_if1.name, grpc_if1.ip4, ifid=grpc_if1.id) if2 = Interface(grpc_if2.name, grpc_if2.ip4, ifid=grpc_if2.id) - self.core_grpc.manager.edges[e.token].interface_1 = if1 - self.core_grpc.manager.edges[e.token].interface_2 = if2 - self.core_grpc.manager.nodes[ + self.core_grpc.edges[e.token].interface_1 = if1 + self.core_grpc.edges[e.token].interface_2 = if2 + self.core_grpc.nodes[ core_id_to_canvas_id[link.node_one_id] ].interfaces.append(if1) - self.core_grpc.manager.nodes[ + self.core_grpc.nodes[ core_id_to_canvas_id[link.node_two_id] ].interfaces.append(if2) @@ -318,13 +318,13 @@ class CanvasGraph(tk.Canvas): node_dst = self.nodes[edge.dst] node_dst.edges.add(edge) - self.core_grpc.manager.add_edge( + self.core_grpc.add_edge( self.core_grpc.session_id, edge.token, node_src.id, node_dst.id ) # draw link info on the edge - if1 = self.core_grpc.manager.edges[edge.token].interface_1 - if2 = self.core_grpc.manager.edges[edge.token].interface_2 + if1 = self.core_grpc.edges[edge.token].interface_1 + if2 = self.core_grpc.edges[edge.token].interface_2 ip4_and_prefix_1 = None ip4_and_prefix_2 = None if if1 is not None: @@ -390,10 +390,10 @@ class CanvasGraph(tk.Canvas): image=image, node_type=node_name, canvas=self, - core_id=self.core_grpc.manager.peek_id(), + core_id=self.core_grpc.peek_id(), ) self.nodes[node.id] = node - self.core_grpc.manager.add_node( + self.core_grpc.add_graph_node( self.core_grpc.session_id, node.id, x, y, node_name ) return node @@ -485,7 +485,7 @@ class CanvasNode: self.moving = None def double_click(self, event): - node_id = self.canvas.core_grpc.manager.nodes[self.id].node_id + node_id = self.canvas.core_grpc.nodes[self.id].node_id state = self.canvas.core_grpc.get_session_state() if state == core_pb2.SessionState.RUNTIME: self.canvas.core_grpc.launch_terminal(node_id) @@ -511,9 +511,7 @@ class CanvasNode: def click_release(self, event): logging.debug(f"click release {self.name}: {event}") self.update_coords() - self.canvas.core_grpc.manager.update_node_location( - self.id, self.x_coord, self.y_coord - ) + self.canvas.core_grpc.update_node_location(self.id, self.x_coord, self.y_coord) self.moving = None def motion(self, event): diff --git a/coretk/coretk/grpcmanagement.py b/coretk/coretk/grpcmanagement.py deleted file mode 100644 index 85d8c8f5..00000000 --- a/coretk/coretk/grpcmanagement.py +++ /dev/null @@ -1,328 +0,0 @@ -""" -Manage useful informations about the nodes, edges and configuration -that can be useful for grpc, acts like a session class -""" -import logging - -from core.api.grpc import core_pb2 -from coretk.coretocanvas import CoreToCanvasMapping -from coretk.interface import Interface, InterfaceManager -from coretk.wlannodeconfig import WlanNodeConfig - -link_layer_nodes = ["switch", "hub", "wlan", "rj45", "tunnel"] -network_layer_nodes = ["router", "host", "PC", "mdr", "prouter", "OVS"] - - -class Node: - def __init__(self, session_id, node_id, node_type, model, x, y, name): - """ - Create an instance of a node - - :param int session_id: session id - :param int node_id: node id - :param core_pb2.NodeType node_type: node type - :param int x: x coordinate - :param int y: coordinate - :param str name: node name - """ - self.session_id = session_id - self.node_id = node_id - self.type = node_type - self.x = x - self.y = y - self.model = model - self.name = name - self.interfaces = [] - - -class Edge: - def __init__(self, session_id, node_id_1, node_type_1, node_id_2, node_type_2): - """ - Create an instance of an edge - :param int session_id: session id - :param int node_id_1: node 1 id - :param int node_type_1: node 1 type - :param core_pb2.NodeType node_id_2: node 2 id - :param core_pb2.NodeType node_type_2: node 2 type - """ - self.session_id = session_id - self.id1 = node_id_1 - self.id2 = node_id_2 - self.type1 = node_type_1 - self.type2 = node_type_2 - self.interface_1 = None - self.interface_2 = None - - -class GrpcManager: - def __init__(self, grpc): - self.nodes = {} - self.edges = {} - self.id = 1 - # A list of id for re-use, keep in increasing order - self.reusable = [] - self.preexisting = set() - self.core_grpc = grpc - # self.update_preexisting_ids() - # self.core_id_to_canvas_id = {} - self.interfaces_manager = InterfaceManager() - # map tuple(core_node_id, interface_id) to and edge - # self.node_id_and_interface_to_edge_token = {} - self.core_mapping = CoreToCanvasMapping() - self.wlanconfig_management = WlanNodeConfig() - - def update_preexisting_ids(self): - """ - get preexisting node ids - :return: - """ - max_id = 0 - client = self.core_grpc.core - sessions = client.get_sessions().sessions - for session_summary in sessions: - session = client.get_session(session_summary.id).session - for node in session.nodes: - if node.id > max_id: - max_id = node.id - self.preexisting.append(node.id) - self.id = max_id + 1 - self.update_reusable_id() - - def peek_id(self): - """ - Peek the next id to be used - - :return: nothing - """ - if len(self.reusable) == 0: - return self.id - else: - return self.reusable[0] - - def get_id(self): - """ - Get the next node id as well as update id status and reusable ids - - :rtype: int - :return: the next id to be used - """ - if len(self.reusable) == 0: - new_id = self.id - self.id = self.id + 1 - return new_id - else: - return self.reusable.pop(0) - - def add_node(self, session_id, canvas_id, x, y, name): - """ - Add node, with information filled in, to grpc manager - - :param int session_id: session id - :param int canvas_id: node's canvas id - :param int x: x coord - :param int y: y coord - :param str name: node type - :return: nothing - """ - node_type = None - node_model = None - if name in link_layer_nodes: - if name == "switch": - node_type = core_pb2.NodeType.SWITCH - elif name == "hub": - node_type = core_pb2.NodeType.HUB - elif name == "wlan": - node_type = core_pb2.NodeType.WIRELESS_LAN - elif name == "rj45": - node_type = core_pb2.NodeType.RJ45 - elif name == "tunnel": - node_type = core_pb2.NodeType.TUNNEL - elif name in network_layer_nodes: - node_type = core_pb2.NodeType.DEFAULT - node_model = name - else: - logging.error("grpcmanagemeny.py INVALID node name") - nid = self.get_id() - create_node = Node(session_id, nid, node_type, node_model, x, y, name) - - # set default configuration for wireless node - self.wlanconfig_management.set_default_config(node_type, nid) - - self.nodes[canvas_id] = create_node - self.core_mapping.map_core_id_to_canvas_id(nid, canvas_id) - # self.core_id_to_canvas_id[nid] = canvas_id - logging.debug( - "Adding node to GrpcManager.. Session id: %s, Coords: (%s, %s), Name: %s", - session_id, - x, - y, - name, - ) - - def add_preexisting_node(self, canvas_node, session_id, core_node, name): - """ - Add preexisting nodes to grpc manager - - :param str name: node_type - :param core_pb2.Node core_node: core node grpc message - :param coretk.graph.CanvasNode canvas_node: canvas node - :param int session_id: session id - :return: nothing - """ - - # update the next available id - core_id = core_node.id - if self.id is None or core_id >= self.id: - self.id = core_id + 1 - self.preexisting.add(core_id) - n = Node( - session_id, - core_id, - core_node.type, - core_node.model, - canvas_node.x_coord, - canvas_node.y_coord, - name, - ) - self.nodes[canvas_node.id] = n - - def update_node_location(self, canvas_id, new_x, new_y): - """ - update node - - :param int canvas_id: canvas id of that node - :param int new_x: new x coord - :param int new_y: new y coord - :return: nothing - """ - self.nodes[canvas_id].x = new_x - self.nodes[canvas_id].y = new_y - - def update_reusable_id(self): - """ - Update available id for reuse - - :return: nothing - """ - if len(self.preexisting) > 0: - for i in range(1, self.id): - if i not in self.preexisting: - self.reusable.append(i) - - 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, edge, src_canvas_id, dst_canvas_id): - """ - Create the interface for the two end of an edge, add a copy to node's interfaces - - :param coretk.grpcmanagement.Edge edge: edge to add interfaces to - :param int src_canvas_id: canvas id for the source node - :param int dst_canvas_id: canvas id for the destination node - :return: nothing - """ - src_interface = None - dst_interface = None - print("create interface") - self.interfaces_manager.new_subnet() - - src_node = self.nodes[src_canvas_id] - if src_node.model in network_layer_nodes: - ifid = len(src_node.interfaces) - name = "eth" + str(ifid) - src_interface = Interface( - name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address()) - ) - self.nodes[src_canvas_id].interfaces.append(src_interface) - logging.debug( - "Create source interface 1... IP: %s, name: %s", - src_interface.ipv4, - src_interface.name, - ) - - dst_node = self.nodes[dst_canvas_id] - if dst_node.model in network_layer_nodes: - ifid = len(dst_node.interfaces) - name = "eth" + str(ifid) - dst_interface = Interface( - name=name, ifid=ifid, ipv4=str(self.interfaces_manager.get_address()) - ) - self.nodes[dst_canvas_id].interfaces.append(dst_interface) - logging.debug( - "Create destination interface... IP: %s, name: %s", - dst_interface.ipv4, - dst_interface.name, - ) - - edge.interface_1 = src_interface - edge.interface_2 = dst_interface - return src_interface, dst_interface - - def add_edge(self, session_id, token, canvas_id_1, canvas_id_2): - """ - Add an edge to grpc manager - - :param int session_id: core session id - :param tuple(int, int) token: edge's identification in the canvas - :param int canvas_id_1: canvas id of source node - :param int canvas_id_2: canvas_id of destination node - - :return: nothing - """ - if canvas_id_1 in self.nodes and canvas_id_2 in self.nodes: - edge = Edge( - session_id, - self.nodes[canvas_id_1].node_id, - self.nodes[canvas_id_1].type, - self.nodes[canvas_id_2].node_id, - self.nodes[canvas_id_2].type, - ) - self.edges[token] = edge - src_interface, dst_interface = self.create_interface( - edge, canvas_id_1, canvas_id_2 - ) - node_one_id = self.nodes[canvas_id_1].node_id - node_two_id = self.nodes[canvas_id_2].node_id - - # provide a way to get an edge from a core node and an interface id - if src_interface is not None: - # self.node_id_and_interface_to_edge_token[tuple([node_one_id, src_interface.id])] = token - self.core_mapping.map_node_and_interface_to_canvas_edge( - node_one_id, src_interface.id, token - ) - logging.debug( - "map node id %s, interface_id %s to edge token %s", - node_one_id, - src_interface.id, - token, - ) - - if dst_interface is not None: - # self.node_id_and_interface_to_edge_token[tuple([node_two_id, dst_interface.id])] = token - self.core_mapping.map_node_and_interface_to_canvas_edge( - node_two_id, dst_interface.id, token - ) - logging.debug( - "map node id %s, interface_id %s to edge token %s", - node_two_id, - dst_interface.id, - token, - ) - - logging.debug("Adding edge to grpc manager...") - else: - logging.error("grpcmanagement.py INVALID CANVAS NODE ID") diff --git a/coretk/coretk/linkinfo.py b/coretk/coretk/linkinfo.py index 17bc99c8..a306bfdc 100644 --- a/coretk/coretk/linkinfo.py +++ b/coretk/coretk/linkinfo.py @@ -130,7 +130,7 @@ class Throughput: iid = t.interface_id tp = t.throughput # token = self.grpc_manager.node_id_and_interface_to_edge_token[nid, iid] - token = self.core_grpc.manager.core_mapping.get_token_from_node_and_interface( + token = self.core_grpc.core_mapping.get_token_from_node_and_interface( nid, iid ) print(token) diff --git a/coretk/coretk/wirelessconnection.py b/coretk/coretk/wirelessconnection.py index 3e4a98f8..0c45e896 100644 --- a/coretk/coretk/wirelessconnection.py +++ b/coretk/coretk/wirelessconnection.py @@ -5,10 +5,10 @@ from core.api.grpc import core_pb2 class WirelessConnection: - def __init__(self, canvas, grpc): + def __init__(self, canvas, core_grpc): self.canvas = canvas - self.core_grpc = grpc - self.core_mapping = grpc.manager.core_mapping + self.core_grpc = core_grpc + self.core_mapping = core_grpc.core_mapping # map a (node_one_id, node_two_id) to a wlan canvas id self.map = {} From 6fa3beb1c1442871dbaa08a7d33edf9753946c38 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 13:42:49 -0700 Subject: [PATCH 03/12] refactoring to change core_grpc to core, and update CoreGrpc to be CoreClient and have core now be client, also refactored usages of application to be just app to keep it short --- coretk/coretk/app.py | 8 +-- coretk/coretk/{coregrpc.py => coreclient.py} | 72 ++++++++++---------- coretk/coretk/coremenubar.py | 44 ++++++------ coretk/coretk/coretoolbar.py | 14 ++-- coretk/coretk/coretoolbarhelp.py | 19 ++---- coretk/coretk/dialogs/sessionoptions.py | 8 +-- coretk/coretk/dialogs/sessions.py | 10 +-- coretk/coretk/graph.py | 56 ++++++++------- coretk/coretk/graph_helper.py | 4 +- coretk/coretk/linkinfo.py | 10 ++- coretk/coretk/menuaction.py | 32 ++++----- coretk/coretk/setwallpaper.py | 54 +++++++-------- coretk/coretk/sizeandscale.py | 34 ++++----- coretk/coretk/wirelessconnection.py | 5 +- 14 files changed, 176 insertions(+), 194 deletions(-) rename coretk/coretk/{coregrpc.py => coreclient.py} (90%) diff --git a/coretk/coretk/app.py b/coretk/coretk/app.py index bcc43e43..72749524 100644 --- a/coretk/coretk/app.py +++ b/coretk/coretk/app.py @@ -1,7 +1,7 @@ import logging import tkinter as tk -from coretk.coregrpc import CoreGrpc +from coretk.coreclient import CoreClient from coretk.coremenubar import CoreMenubar from coretk.coretoolbar import CoreToolbar from coretk.graph import CanvasGraph @@ -25,12 +25,12 @@ class Application(tk.Frame): self.radiovar = tk.IntVar(value=1) self.show_grid_var = tk.IntVar(value=1) self.adjust_to_dim_var = tk.IntVar(value=0) - self.core_grpc = CoreGrpc(self) + self.core = CoreClient(self) self.setup_app() self.create_menu() self.create_widgets() self.draw_canvas() - self.core_grpc.set_up() + self.core.set_up() def setup_app(self): self.master.title("CORE") @@ -54,7 +54,7 @@ class Application(tk.Frame): def draw_canvas(self): self.canvas = CanvasGraph( - self, self.core_grpc, background="#cccccc", scrollregion=(0, 0, 1200, 1000) + self, self.core, background="#cccccc", scrollregion=(0, 0, 1200, 1000) ) self.canvas.pack(fill=tk.BOTH, expand=True) diff --git a/coretk/coretk/coregrpc.py b/coretk/coretk/coreclient.py similarity index 90% rename from coretk/coretk/coregrpc.py rename to coretk/coretk/coreclient.py index 94f5ca7b..e5ba838e 100644 --- a/coretk/coretk/coregrpc.py +++ b/coretk/coretk/coreclient.py @@ -56,13 +56,13 @@ class Edge: self.interface_2 = None -class CoreGrpc: - def __init__(self, app, sid=None): +class CoreClient: + def __init__(self, app): """ Create a CoreGrpc instance """ - self.core = client.CoreGrpcClient() - self.session_id = sid + self.client = client.CoreGrpcClient() + self.session_id = None self.node_ids = [] self.app = app self.master = app.master @@ -99,9 +99,9 @@ class CoreGrpc: def join_session(self, session_id): # query session and set as current session self.session_id = session_id - response = self.core.get_session(self.session_id) + response = self.client.get_session(self.session_id) logging.info("joining session(%s): %s", self.session_id, response) - self.core.events(self.session_id, self.handle_events) + self.client.events(self.session_id, self.handle_events) # set title to session self.master.title(f"CORE Session({self.session_id})") @@ -129,7 +129,7 @@ class CoreGrpc: :return: nothing """ - response = self.core.create_session() + response = self.client.create_session() logging.info("created session: %s", response) self.join_session(response.session_id) @@ -138,15 +138,15 @@ class CoreGrpc: sid = self.session_id else: sid = custom_sid - response = self.core.delete_session(sid) + response = self.client.delete_session(sid) logging.info("Deleted session result: %s", response) - def terminate_session(self, custom_sid=None): + def shutdown_session(self, custom_sid=None): if custom_sid is None: sid = self.session_id else: sid = custom_sid - s = self.core.get_session(sid).session + s = self.client.get_session(sid).session # delete links and nodes from running session if s.state == core_pb2.SessionState.RUNTIME: self.set_session_state("datacollect", sid) @@ -160,8 +160,8 @@ class CoreGrpc: :return: existing sessions """ - self.core.connect() - response = self.core.get_sessions() + self.client.connect() + response = self.client.get_sessions() # if there are no sessions, create a new session, else join a session sessions = response.sessions @@ -172,7 +172,7 @@ class CoreGrpc: dialog.show() def get_session_state(self): - response = self.core.get_session(self.session_id) + response = self.client.get_session(self.session_id) # logging.info("get session: %s", response) return response.session.state @@ -190,27 +190,29 @@ class CoreGrpc: response = None if state == "configuration": - response = self.core.set_session_state( + response = self.client.set_session_state( sid, core_pb2.SessionState.CONFIGURATION ) elif state == "instantiation": - response = self.core.set_session_state( + response = self.client.set_session_state( sid, core_pb2.SessionState.INSTANTIATION ) elif state == "datacollect": - response = self.core.set_session_state( + response = self.client.set_session_state( sid, core_pb2.SessionState.DATACOLLECT ) elif state == "shutdown": - response = self.core.set_session_state(sid, core_pb2.SessionState.SHUTDOWN) + response = self.client.set_session_state( + sid, core_pb2.SessionState.SHUTDOWN + ) elif state == "runtime": - response = self.core.set_session_state(sid, core_pb2.SessionState.RUNTIME) + response = self.client.set_session_state(sid, core_pb2.SessionState.RUNTIME) elif state == "definition": - response = self.core.set_session_state( + response = self.client.set_session_state( sid, core_pb2.SessionState.DEFINITION ) elif state == "none": - response = self.core.set_session_state(sid, core_pb2.SessionState.NONE) + response = self.client.set_session_state(sid, core_pb2.SessionState.NONE) else: logging.error("coregrpc.py: set_session_state: INVALID STATE") @@ -218,7 +220,7 @@ class CoreGrpc: def edit_node(self, node_id, x, y): position = core_pb2.Position(x=x, y=y) - response = self.core.edit_node(self.session_id, node_id, position) + response = self.client.edit_node(self.session_id, node_id, position) logging.info("updated node id %s: %s", node_id, response) def delete_nodes(self, delete_session=None): @@ -226,8 +228,8 @@ class CoreGrpc: sid = self.session_id else: sid = delete_session - for node in self.core.get_session(sid).session.nodes: - response = self.core.delete_node(self.session_id, node.id) + for node in self.client.get_session(sid).session.nodes: + response = self.client.delete_node(self.session_id, node.id) logging.info("delete nodes %s", response) def delete_links(self, delete_session=None): @@ -237,8 +239,8 @@ class CoreGrpc: else: sid = delete_session - for link in self.core.get_session(sid).session.links: - response = self.core.delete_link( + for link in self.client.get_session(sid).session.links: + response = self.client.delete_link( self.session_id, link.node_one_id, link.node_two_id, @@ -259,7 +261,7 @@ class CoreGrpc: wlan_configs=None, mobility_configs=None, ): - response = self.core.start_session( + response = self.client.start_session( session_id=self.session_id, nodes=nodes, links=links, @@ -268,7 +270,7 @@ class CoreGrpc: logging.debug("Start session %s, result: %s", self.session_id, response.result) def stop_session(self): - response = self.core.stop_session(session_id=self.session_id) + response = self.client.stop_session(session_id=self.session_id) logging.debug("coregrpc.py Stop session, result: %s", response.result) # TODO no need, might get rid of this @@ -285,11 +287,11 @@ class CoreGrpc: """ if1 = self.create_interface(type1, edge.interface_1) if2 = self.create_interface(type2, edge.interface_2) - response = self.core.add_link(self.session_id, id1, id2, if1, if2) + response = self.client.add_link(self.session_id, id1, id2, if1, if2) logging.info("created link: %s", response) def launch_terminal(self, node_id): - response = self.core.get_node_terminal(self.session_id, node_id) + response = self.client.get_node_terminal(self.session_id, node_id) logging.info("get terminal %s", response.terminal) os.system("xterm -e %s &" % response.terminal) @@ -300,9 +302,9 @@ class CoreGrpc: :param str file_path: file path that user pick :return: nothing """ - response = self.core.save_xml(self.session_id, file_path) + response = self.client.save_xml(self.session_id, file_path) logging.info("coregrpc.py save xml %s", response) - self.core.events(self.session_id, self.handle_events) + self.client.events(self.session_id, self.handle_events) def open_xml(self, file_path): """ @@ -311,7 +313,7 @@ class CoreGrpc: :param str file_path: file to open :return: session id """ - response = self.core.open_xml(file_path) + response = self.client.open_xml(file_path) logging.debug("open xml: %s", response) self.join_session(response.session_id) @@ -322,7 +324,7 @@ class CoreGrpc: :return: nothing """ logging.debug("Close grpc") - self.core.close() + self.client.close() def peek_id(self): """ @@ -353,7 +355,7 @@ class CoreGrpc: 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.core.add_node(self.session_id, node) + 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() @@ -362,7 +364,7 @@ class CoreGrpc: d["jitter"] = "0" d["delay"] = "20000" d["error"] = "0" - r = self.core.set_wlan_config(self.session_id, node_id, d) + r = self.client.set_wlan_config(self.session_id, node_id, d) logging.debug("set wlan config %s", r) return response.node_id diff --git a/coretk/coretk/coremenubar.py b/coretk/coretk/coremenubar.py index aa00a927..7b3f2633 100644 --- a/coretk/coretk/coremenubar.py +++ b/coretk/coretk/coremenubar.py @@ -9,19 +9,19 @@ class CoreMenubar(object): Core menubar """ - def __init__(self, application, master, menubar): + def __init__(self, app, master, menubar): """ Create a CoreMenubar instance :param master: :param tkinter.Menu menubar: menubar object - :param coretk.app.Application application: application object + :param coretk.app.Application app: application object """ self.menubar = menubar self.master = master - self.application = application - self.menuaction = action.MenuAction(application, master) - self.menu_action = MenuAction(self.application, self.master) + self.app = app + self.menuaction = action.MenuAction(app, master) + self.menu_action = MenuAction(self.app, self.master) # def on_quit(self): # """ @@ -649,23 +649,23 @@ class CoreMenubar(object): :return: nothing """ - self.application.bind_all("", action.file_new_shortcut) - self.application.bind_all("", action.file_open_shortcut) - self.application.bind_all("", action.file_save_shortcut) - self.application.bind_all("", action.edit_undo_shortcut) - self.application.bind_all("", action.edit_redo_shortcut) - self.application.bind_all("", action.edit_cut_shortcut) - self.application.bind_all("", action.edit_copy_shortcut) - self.application.bind_all("", action.edit_paste_shortcut) - self.application.bind_all("", action.edit_select_all_shortcut) - self.application.bind_all("", action.edit_select_adjacent_shortcut) - self.application.bind_all("", action.edit_find_shortcut) - self.application.bind_all("", action.canvas_previous_shortcut) - self.application.bind_all("", action.canvas_next_shortcut) - self.application.bind_all("", action.canvas_first_shortcut) - self.application.bind_all("", action.canvas_last_shortcut) - self.application.bind_all("", action.view_zoom_in_shortcut) - self.application.bind_all("", action.view_zoom_out_shortcut) + self.app.bind_all("", action.file_new_shortcut) + self.app.bind_all("", action.file_open_shortcut) + self.app.bind_all("", action.file_save_shortcut) + self.app.bind_all("", action.edit_undo_shortcut) + self.app.bind_all("", action.edit_redo_shortcut) + self.app.bind_all("", action.edit_cut_shortcut) + self.app.bind_all("", action.edit_copy_shortcut) + self.app.bind_all("", action.edit_paste_shortcut) + self.app.bind_all("", action.edit_select_all_shortcut) + self.app.bind_all("", action.edit_select_adjacent_shortcut) + self.app.bind_all("", action.edit_find_shortcut) + self.app.bind_all("", action.canvas_previous_shortcut) + self.app.bind_all("", action.canvas_next_shortcut) + self.app.bind_all("", action.canvas_first_shortcut) + self.app.bind_all("", action.canvas_last_shortcut) + self.app.bind_all("", action.view_zoom_in_shortcut) + self.app.bind_all("", action.view_zoom_out_shortcut) def create_core_menubar(self): """ diff --git a/coretk/coretk/coretoolbar.py b/coretk/coretk/coretoolbar.py index 78688725..5d7c05ae 100644 --- a/coretk/coretk/coretoolbar.py +++ b/coretk/coretk/coretoolbar.py @@ -25,14 +25,14 @@ class CoreToolbar(object): Core toolbar class """ - def __init__(self, application, edit_frame, menubar): + def __init__(self, app, edit_frame, menubar): """ Create a CoreToolbar instance :param tkinter.Frame edit_frame: edit frame """ - self.application = application - self.master = application.master + self.app = app + self.master = app.master self.edit_frame = edit_frame self.menubar = menubar self.radio_value = tk.IntVar() @@ -161,7 +161,7 @@ class CoreToolbar(object): :return: nothing """ logging.debug("Click START STOP SESSION button") - helper = CoreToolbarHelp(self.application) + helper = CoreToolbarHelp(self.app) self.destroy_children_widgets() self.canvas.mode = GraphMode.SELECT @@ -593,11 +593,7 @@ class CoreToolbar(object): """ logging.debug("Click on STOP button ") self.destroy_children_widgets() - - # self.canvas.core_grpc.set_session_state(SessionStateEnum.DATACOLLECT.value) - # self.canvas.core_grpc.delete_links() - # self.canvas.core_grpc.delete_nodes() - self.canvas.core_grpc.stop_session() + self.app.core.stop_session() self.create_toolbar() def click_run_button(self): diff --git a/coretk/coretk/coretoolbarhelp.py b/coretk/coretk/coretoolbarhelp.py index b26269db..ca30141d 100644 --- a/coretk/coretk/coretoolbarhelp.py +++ b/coretk/coretk/coretoolbarhelp.py @@ -15,8 +15,7 @@ class CoreToolbarHelp: :return: nothing """ nodes = [] - core = self.app.core_grpc - for node in core.nodes.values(): + for node in self.app.core.nodes.values(): pos = core_pb2.Position(x=int(node.x), y=int(node.y)) n = core_pb2.Node( id=node.node_id, type=node.type, position=pos, model=node.model @@ -32,14 +31,9 @@ class CoreToolbarHelp: :return: list of protobuf links """ links = [] - core = self.app.core_grpc - for edge in core.edges.values(): - interface_one = self.app.core_grpc.create_interface( - edge.type1, edge.interface_1 - ) - interface_two = self.app.core_grpc.create_interface( - edge.type2, edge.interface_2 - ) + for edge in self.app.core.edges.values(): + interface_one = self.app.core.create_interface(edge.type1, edge.interface_1) + interface_two = self.app.core.create_interface(edge.type2, edge.interface_2) # TODO for now only consider the basic cases if ( edge.type1 == core_pb2.NodeType.WIRELESS_LAN @@ -61,8 +55,7 @@ class CoreToolbarHelp: def get_wlan_configuration_list(self): configs = [] - core = self.app.core_grpc - manager_configs = core.wlanconfig_management.configurations + manager_configs = self.app.core.wlanconfig_management.configurations for key in manager_configs: cnf = core_pb2.WlanConfig(node_id=key, config=manager_configs[key]) configs.append(cnf) @@ -72,4 +65,4 @@ class CoreToolbarHelp: nodes = self.get_node_list() links = self.get_link_list() wlan_configs = self.get_wlan_configuration_list() - self.app.core_grpc.start_session(nodes, links, wlan_configs=wlan_configs) + self.app.core.start_session(nodes, links, wlan_configs=wlan_configs) diff --git a/coretk/coretk/dialogs/sessionoptions.py b/coretk/coretk/dialogs/sessionoptions.py index a34c6658..6279d844 100644 --- a/coretk/coretk/dialogs/sessionoptions.py +++ b/coretk/coretk/dialogs/sessionoptions.py @@ -18,8 +18,8 @@ class SessionOptionsDialog(Dialog): self.draw() def draw(self): - session_id = self.master.core_grpc.session_id - response = self.master.core_grpc.core.get_session_options(session_id) + session_id = self.app.core.session_id + response = self.app.core.client.get_session_options(session_id) logging.info("session options: %s", response) self.options = response.config self.values = configutils.create_config(self, self.options, PAD_X, PAD_Y) @@ -28,7 +28,7 @@ class SessionOptionsDialog(Dialog): def save(self): config = configutils.parse_config(self.options, self.values) - session_id = self.master.core_grpc.session_id - response = self.master.core_grpc.core.set_session_options(session_id, config) + session_id = self.app.core.session_id + response = self.app.core.client.set_session_options(session_id, config) logging.info("saved session config: %s", response) self.destroy() diff --git a/coretk/coretk/dialogs/sessions.py b/coretk/coretk/dialogs/sessions.py index b2bd90f0..b7c4d128 100644 --- a/coretk/coretk/dialogs/sessions.py +++ b/coretk/coretk/dialogs/sessions.py @@ -12,7 +12,7 @@ class SessionsDialog(Dialog): """ create session table instance - :param coretk.coregrpc.CoreGrpc grpc: coregrpc + :param coretk.coreclient.CoreClient grpc: coregrpc :param root.master master: """ super().__init__(master, app, "Sessions", modal=True) @@ -51,7 +51,7 @@ class SessionsDialog(Dialog): self.tree.column("nodes", stretch=tk.YES) self.tree.heading("nodes", text="Node Count") - response = self.app.core_grpc.core.get_sessions() + response = self.app.core.client.get_sessions() logging.info("sessions: %s", response) for index, session in enumerate(response.sessions): state_name = core_pb2.SessionState.Enum.Name(session.state) @@ -105,7 +105,7 @@ class SessionsDialog(Dialog): b.grid(row=0, column=3, padx=2, sticky="ew") def click_new(self): - self.app.core_grpc.create_new_session() + self.app.core.create_new_session() self.destroy() def click_select(self, event): @@ -142,7 +142,7 @@ class SessionsDialog(Dialog): logging.error("querysessiondrawing.py invalid state") def join_session(self, session_id): - self.app.core_grpc.join_session(session_id) + self.app.core.join_session(session_id) self.destroy() def on_selected(self, event): @@ -151,6 +151,6 @@ class SessionsDialog(Dialog): self.join_session(sid) def shutdown_session(self, sid): - self.app.core_grpc.terminate_session(sid) + self.app.core.shutdown_session(sid) self.click_new() self.destroy() diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py index 7859a8e6..e53a5274 100644 --- a/coretk/coretk/graph.py +++ b/coretk/coretk/graph.py @@ -26,7 +26,7 @@ CORE_EMANE = ["emane"] class CanvasGraph(tk.Canvas): - def __init__(self, master, core_grpc, cnf=None, **kwargs): + def __init__(self, master, core, cnf=None, **kwargs): if cnf is None: cnf = {} kwargs["highlightthickness"] = 0 @@ -45,10 +45,10 @@ class CanvasGraph(tk.Canvas): self.setup_menus() self.setup_bindings() self.draw_grid() - self.core_grpc = core_grpc - self.helper = GraphHelper(self, core_grpc) - self.throughput_draw = Throughput(self, core_grpc) - self.wireless_draw = WirelessConnection(self, core_grpc) + self.core = core + self.helper = GraphHelper(self, core) + self.throughput_draw = Throughput(self, core) + self.wireless_draw = WirelessConnection(self, core) self.is_node_context_opened = False def setup_menus(self): @@ -147,7 +147,7 @@ class CanvasGraph(tk.Canvas): core_id_to_canvas_id[node.id] = n.id # store the node in grpc manager - self.core_grpc.add_preexisting_node(n, session.id, node, name) + self.core.add_preexisting_node(n, session.id, node, name) # draw existing links for link in session.links: @@ -179,7 +179,7 @@ class CanvasGraph(tk.Canvas): n1.edges.add(e) n2.edges.add(e) self.edges[e.token] = e - self.core_grpc.add_edge(session.id, e.token, n1.id, n2.id) + self.core.add_edge(session.id, e.token, n1.id, n2.id) self.helper.redraw_antenna(link, n1, n2) @@ -208,14 +208,14 @@ class CanvasGraph(tk.Canvas): # TODO will include throughput and ipv6 in the future if1 = Interface(grpc_if1.name, grpc_if1.ip4, ifid=grpc_if1.id) if2 = Interface(grpc_if2.name, grpc_if2.ip4, ifid=grpc_if2.id) - self.core_grpc.edges[e.token].interface_1 = if1 - self.core_grpc.edges[e.token].interface_2 = if2 - self.core_grpc.nodes[ - core_id_to_canvas_id[link.node_one_id] - ].interfaces.append(if1) - self.core_grpc.nodes[ - core_id_to_canvas_id[link.node_two_id] - ].interfaces.append(if2) + self.core.edges[e.token].interface_1 = if1 + self.core.edges[e.token].interface_2 = if2 + self.core.nodes[core_id_to_canvas_id[link.node_one_id]].interfaces.append( + if1 + ) + self.core.nodes[core_id_to_canvas_id[link.node_two_id]].interfaces.append( + if2 + ) # lift the nodes so they on top of the links for i in self.find_withtag("node"): @@ -318,13 +318,13 @@ class CanvasGraph(tk.Canvas): node_dst = self.nodes[edge.dst] node_dst.edges.add(edge) - self.core_grpc.add_edge( - self.core_grpc.session_id, edge.token, node_src.id, node_dst.id + self.core.add_edge( + self.core.session_id, edge.token, node_src.id, node_dst.id ) # draw link info on the edge - if1 = self.core_grpc.edges[edge.token].interface_1 - if2 = self.core_grpc.edges[edge.token].interface_2 + if1 = self.core.edges[edge.token].interface_1 + if2 = self.core.edges[edge.token].interface_2 ip4_and_prefix_1 = None ip4_and_prefix_2 = None if if1 is not None: @@ -390,12 +390,10 @@ class CanvasGraph(tk.Canvas): image=image, node_type=node_name, canvas=self, - core_id=self.core_grpc.peek_id(), + core_id=self.core.peek_id(), ) self.nodes[node.id] = node - self.core_grpc.add_graph_node( - self.core_grpc.session_id, node.id, x, y, node_name - ) + self.core.add_graph_node(self.core.session_id, node.id, x, y, node_name) return node @@ -485,10 +483,10 @@ class CanvasNode: self.moving = None def double_click(self, event): - node_id = self.canvas.core_grpc.nodes[self.id].node_id - state = self.canvas.core_grpc.get_session_state() + node_id = self.canvas.core.nodes[self.id].node_id + state = self.canvas.core.get_session_state() if state == core_pb2.SessionState.RUNTIME: - self.canvas.core_grpc.launch_terminal(node_id) + self.canvas.core.launch_terminal(node_id) else: self.canvas.canvas_action.display_configuration(self) # if self.node_type in CORE_NODES: @@ -511,7 +509,7 @@ class CanvasNode: def click_release(self, event): logging.debug(f"click release {self.name}: {event}") self.update_coords() - self.canvas.core_grpc.update_node_location(self.id, self.x_coord, self.y_coord) + self.canvas.core.update_node_location(self.id, self.x_coord, self.y_coord) self.moving = None def motion(self, event): @@ -529,8 +527,8 @@ class CanvasNode: new_x, new_y = self.canvas.coords(self.id) - if self.canvas.core_grpc.get_session_state() == core_pb2.SessionState.RUNTIME: - self.canvas.core_grpc.edit_node(self.core_id, int(new_x), int(new_y)) + if self.canvas.core.get_session_state() == core_pb2.SessionState.RUNTIME: + self.canvas.core.edit_node(self.core_id, int(new_x), int(new_y)) for edge in self.edges: x1, y1, x2, y2 = self.canvas.coords(edge.id) diff --git a/coretk/coretk/graph_helper.py b/coretk/coretk/graph_helper.py index ba58a435..bdedd65e 100644 --- a/coretk/coretk/graph_helper.py +++ b/coretk/coretk/graph_helper.py @@ -11,12 +11,12 @@ CANVAS_COMPONENT_TAGS = ["edge", "node", "nodename", "wallpaper", "linkinfo"] class GraphHelper: - def __init__(self, canvas, grpc): + def __init__(self, canvas, core): """ create an instance of GraphHelper object """ self.canvas = canvas - self.core_grpc = grpc + self.core = core def delete_canvas_components(self): """ diff --git a/coretk/coretk/linkinfo.py b/coretk/coretk/linkinfo.py index a306bfdc..916e8dfb 100644 --- a/coretk/coretk/linkinfo.py +++ b/coretk/coretk/linkinfo.py @@ -22,7 +22,7 @@ class LinkInfo: self.edge = edge # self.edge_id = edge.id self.radius = 37 - self.core_grpc = self.canvas.core_grpc + self.core = self.canvas.core self.ip4_address_1 = ip4_src self.ip6_address_1 = ip6_src @@ -104,13 +104,13 @@ class LinkInfo: class Throughput: - def __init__(self, canvas, core_grpc): + def __init__(self, canvas, core): """ create an instance of Throughput object :param coretk.app.Application app: application """ self.canvas = canvas - self.core_grpc = core_grpc + self.core = core # edge canvas id mapped to throughput value self.tracker = {} # map an edge canvas id to a throughput canvas id @@ -130,9 +130,7 @@ class Throughput: iid = t.interface_id tp = t.throughput # token = self.grpc_manager.node_id_and_interface_to_edge_token[nid, iid] - token = self.core_grpc.core_mapping.get_token_from_node_and_interface( - nid, iid - ) + token = self.core.core_mapping.get_token_from_node_and_interface(nid, iid) print(token) edge_id = self.canvas.edges[token].id diff --git a/coretk/coretk/menuaction.py b/coretk/coretk/menuaction.py index 4ed5e529..7598f210 100644 --- a/coretk/coretk/menuaction.py +++ b/coretk/coretk/menuaction.py @@ -321,10 +321,9 @@ class MenuAction: Actions performed when choosing menu items """ - def __init__(self, application, master): + def __init__(self, app, master): self.master = master - self.application = application - self.core_grpc = application.core_grpc + self.app = app def prompt_save_running_session(self): """ @@ -335,21 +334,20 @@ class MenuAction: logging.info( "menuaction.py: clean_nodes_links_and_set_configuration() Exiting the program" ) - grpc = self.application.core_grpc - state = grpc.get_session_state() + state = self.app.core.get_session_state() if ( state == core_pb2.SessionState.SHUTDOWN or state == core_pb2.SessionState.DEFINITION ): - grpc.delete_session() + self.app.core.delete_session() else: msgbox = messagebox.askyesnocancel("stop", "Stop the running session?") if msgbox or msgbox is False: if msgbox: - grpc.stop_session() - grpc.delete_session() + self.app.core.stop_session() + self.app.core.delete_session() def on_quit(self): """ @@ -358,23 +356,21 @@ class MenuAction: :return: nothing """ self.prompt_save_running_session() - # self.application.core_grpc.close() - self.application.quit() + self.app.quit() def file_save_as_xml(self): logging.info("menuaction.py file_save_as_xml()") - grpc = self.application.core_grpc file_path = filedialog.asksaveasfilename( initialdir=SAVEDIR, title="Save As", filetypes=(("EmulationScript XML files", "*.xml"), ("All files", "*")), defaultextension=".xml", ) - grpc.save_xml(file_path) + self.app.core.save_xml(file_path) def file_open_xml(self): logging.info("menuaction.py file_open_xml()") - self.application.is_open_xml = True + self.app.is_open_xml = True file_path = filedialog.askopenfilename( initialdir=SAVEDIR, title="Open", @@ -382,17 +378,17 @@ class MenuAction: ) # clean up before opening a new session self.prompt_save_running_session() - self.application.core_grpc.open_xml(file_path) + self.app.core.open_xml(file_path) # Todo might not need # self.application.core_editbar.destroy_children_widgets() # self.application.core_editbar.create_toolbar() def canvas_size_and_scale(self): - self.application.size_and_scale = SizeAndScale(self.application) + self.app.size_and_scale = SizeAndScale(self.app) def canvas_set_wallpaper(self): - self.application.set_wallpaper = CanvasWallpaper(self.application) + self.app.set_wallpaper = CanvasWallpaper(self.app) def help_core_github(self): webbrowser.open_new("https://github.com/coreemu/core") @@ -402,10 +398,10 @@ class MenuAction: def session_options(self): logging.debug("Click session options") - dialog = SessionOptionsDialog(self.application, self.application) + dialog = SessionOptionsDialog(self.app, self.app) dialog.show() def session_change_sessions(self): logging.debug("Click session change sessions") - dialog = SessionsDialog(self.application, self.application) + dialog = SessionsDialog(self.app, self.app) dialog.show() diff --git a/coretk/coretk/setwallpaper.py b/coretk/coretk/setwallpaper.py index beec0162..edace83c 100644 --- a/coretk/coretk/setwallpaper.py +++ b/coretk/coretk/setwallpaper.py @@ -22,24 +22,24 @@ class ScaleOption(enum.Enum): class CanvasWallpaper: - def __init__(self, application): + def __init__(self, app): """ create an instance of CanvasWallpaper object - :param coretk.app.Application application: root application + :param coretk.app.Application app: root application """ - self.application = application - self.canvas = self.application.canvas + self.app = app + self.canvas = self.app.canvas self.top = tk.Toplevel() self.top.title("Set Canvas Wallpaper") self.radiovar = tk.IntVar() - print(self.application.radiovar.get()) - self.radiovar.set(self.application.radiovar.get()) + print(self.app.radiovar.get()) + self.radiovar.set(self.app.radiovar.get()) self.show_grid_var = tk.IntVar() - self.show_grid_var.set(self.application.show_grid_var.get()) + self.show_grid_var.set(self.app.show_grid_var.get()) self.adjust_to_dim_var = tk.IntVar() - self.adjust_to_dim_var.set(self.application.adjust_to_dim_var.get()) + self.adjust_to_dim_var.set(self.app.adjust_to_dim_var.get()) self.create_image_label() self.create_text_label() @@ -181,7 +181,7 @@ class CanvasWallpaper: :return: nothing """ - canvas = self.application.canvas + canvas = self.app.canvas grid = canvas.find_withtag("rectangle")[0] x0, y0, x1, y1 = canvas.coords(grid) canvas_w = abs(x0 - x1) @@ -215,7 +215,7 @@ class CanvasWallpaper: cropped_tk = ImageTk.PhotoImage(cropped) # place left corner of image to the left corner of the canvas - self.application.croppedwallpaper = cropped_tk + self.app.croppedwallpaper = cropped_tk self.delete_canvas_components(["wallpaper"]) # self.delete_previous_wallpaper() @@ -223,7 +223,7 @@ class CanvasWallpaper: wid = self.canvas.create_image( (cropx / 2, cropy / 2), image=cropped_tk, tags="wallpaper" ) - self.application.wallpaper_id = wid + self.app.wallpaper_id = wid def center(self, img): """ @@ -252,13 +252,13 @@ class CanvasWallpaper: cropped_tk = ImageTk.PhotoImage(cropped) # place the center of the image at the center of the canvas - self.application.croppedwallpaper = cropped_tk + self.app.croppedwallpaper = cropped_tk self.delete_canvas_components(["wallpaper"]) # self.delete_previous_wallpaper() wid = self.canvas.create_image( (canvas_w / 2, canvas_h / 2), image=cropped_tk, tags="wallpaper" ) - self.application.wallpaper_id = wid + self.app.wallpaper_id = wid def scaled(self, img): """ @@ -270,7 +270,7 @@ class CanvasWallpaper: canvas_w, canvas_h = self.get_canvas_width_and_height() resized_image = img.resize((int(canvas_w), int(canvas_h)), Image.ANTIALIAS) image_tk = ImageTk.PhotoImage(resized_image) - self.application.croppedwallpaper = image_tk + self.app.croppedwallpaper = image_tk self.delete_canvas_components(["wallpaper"]) # self.delete_previous_wallpaper() @@ -278,7 +278,7 @@ class CanvasWallpaper: wid = self.canvas.create_image( (canvas_w / 2, canvas_h / 2), image=image_tk, tags="wallpaper" ) - self.application.wallpaper_id = wid + self.app.wallpaper_id = wid def tiled(self, img): return @@ -301,15 +301,15 @@ class CanvasWallpaper: self.delete_canvas_components(["wallpaper"]) self.draw_new_canvas(img_w, img_h) wid = self.canvas.create_image((img_w / 2, img_h / 2), image=image_tk) - self.application.croppedwallpaper = image_tk - self.application.wallpaper_id = wid + self.app.croppedwallpaper = image_tk + self.app.wallpaper_id = wid def show_grid(self): """ :return: nothing """ - self.application.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) + self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) if self.show_grid_var.get() == 0: for i in self.canvas.find_withtag("gridline"): @@ -322,9 +322,9 @@ class CanvasWallpaper: logging.error("setwallpaper.py show_grid invalid value") def save_wallpaper_options(self): - self.application.radiovar.set(self.radiovar.get()) - self.application.show_grid_var.set(self.show_grid_var.get()) - self.application.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) + self.app.radiovar.set(self.radiovar.get()) + self.app.show_grid_var.set(self.show_grid_var.get()) + self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) def click_apply(self): img_link_frame = self.top.grid_slaves(2, 0)[0] @@ -332,23 +332,23 @@ class CanvasWallpaper: if not filename: self.delete_canvas_components(["wallpaper"]) self.top.destroy() - self.application.current_wallpaper = None + self.app.current_wallpaper = None self.save_wallpaper_options() return try: img = Image.open(filename) - self.application.current_wallpaper = img + self.app.current_wallpaper = img except FileNotFoundError: print("invalid filename, draw original white plot") - if self.application.wallpaper_id: - self.canvas.delete(self.application.wallpaper_id) + if self.app.wallpaper_id: + self.canvas.delete(self.app.wallpaper_id) self.top.destroy() return - self.application.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) + self.app.adjust_to_dim_var.set(self.adjust_to_dim_var.get()) if self.adjust_to_dim_var.get() == 0: - self.application.radiovar.set(self.radiovar.get()) + self.app.radiovar.set(self.radiovar.get()) if self.radiovar.get() == ScaleOption.UPPER_LEFT.value: self.upper_left(img) diff --git a/coretk/coretk/sizeandscale.py b/coretk/coretk/sizeandscale.py index 3552c2e5..5c746c39 100644 --- a/coretk/coretk/sizeandscale.py +++ b/coretk/coretk/sizeandscale.py @@ -10,16 +10,16 @@ DRAW_OBJECT_TAGS = ["edge", "node", "nodename", "linkinfo", "antenna"] class SizeAndScale: - def __init__(self, application): + def __init__(self, app): """ create an instance for size and scale object - :param application: main application + :param app: main application """ - self.application = application + self.app = app self.top = tk.Toplevel() self.top.title("Canvas Size and Scale") - self.meter_per_pixel = self.application.canvas.meters_per_pixel + self.meter_per_pixel = self.app.canvas.meters_per_pixel self.size_chart() self.scale_chart() @@ -108,7 +108,7 @@ class SizeAndScale: label = tk.Label(self.top, text="Size") label.grid(sticky=tk.W, padx=5) - canvas = self.application.canvas + canvas = self.app.canvas plot = canvas.find_withtag("rectangle") x0, y0, x1, y1 = canvas.bbox(plot[0]) w = abs(x0 - x1) - 2 @@ -222,7 +222,7 @@ class SizeAndScale: :param int pixel_height: height in pixel :return: nothing """ - canvas = self.application.canvas + canvas = self.app.canvas canvas.config(scrollregion=(0, 0, pixel_width + 200, pixel_height + 200)) # delete old plot and redraw @@ -246,24 +246,24 @@ class SizeAndScale: scale_frame = self.top.grid_slaves(3, 0)[0] meter_per_pixel = float(scale_frame.grid_slaves(0, 1)[0].get()) / 100 - self.application.canvas.meters_per_pixel = meter_per_pixel + self.app.canvas.meters_per_pixel = meter_per_pixel self.redraw_grid(pixel_width, pixel_height) - print(self.application.current_wallpaper) - print(self.application.radiovar) + print(self.app.current_wallpaper) + print(self.app.radiovar) # if there is a current wallpaper showing, redraw it based on current wallpaper options - wallpaper_tool = self.application.set_wallpaper - current_wallpaper = self.application.current_wallpaper + wallpaper_tool = self.app.set_wallpaper + current_wallpaper = self.app.current_wallpaper if current_wallpaper: - if self.application.adjust_to_dim_var.get() == 0: - if self.application.radiovar.get() == ScaleOption.UPPER_LEFT.value: + if self.app.adjust_to_dim_var.get() == 0: + if self.app.radiovar.get() == ScaleOption.UPPER_LEFT.value: wallpaper_tool.upper_left(current_wallpaper) - elif self.application.radiovar.get() == ScaleOption.CENTERED.value: + elif self.app.radiovar.get() == ScaleOption.CENTERED.value: wallpaper_tool.center(current_wallpaper) - elif self.application.radiovar.get() == ScaleOption.SCALED.value: + elif self.app.radiovar.get() == ScaleOption.SCALED.value: wallpaper_tool.scaled(current_wallpaper) - elif self.application.radiovar.get() == ScaleOption.TILED.value: + elif self.app.radiovar.get() == ScaleOption.TILED.value: print("not implemented") - elif self.application.adjust_to_dim_var.get() == 1: + elif self.app.adjust_to_dim_var.get() == 1: wallpaper_tool.canvas_to_image_dimension(current_wallpaper) wallpaper_tool.show_grid() diff --git a/coretk/coretk/wirelessconnection.py b/coretk/coretk/wirelessconnection.py index 0c45e896..d1e17bc5 100644 --- a/coretk/coretk/wirelessconnection.py +++ b/coretk/coretk/wirelessconnection.py @@ -5,10 +5,9 @@ from core.api.grpc import core_pb2 class WirelessConnection: - def __init__(self, canvas, core_grpc): + def __init__(self, canvas, core): self.canvas = canvas - self.core_grpc = core_grpc - self.core_mapping = core_grpc.core_mapping + self.core_mapping = core.core_mapping # map a (node_one_id, node_two_id) to a wlan canvas id self.map = {} From 6c49a73e3883e34f885c577ef4c5ff3d5966ea27 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 13:45:42 -0700 Subject: [PATCH 04/12] removed old image, fixed get image calls in images.py --- coretk/coretk/images.py | 4 ++-- coretk/coretk/switch.png | Bin 5286 -> 0 bytes 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 coretk/coretk/switch.png diff --git a/coretk/coretk/images.py b/coretk/coretk/images.py index 3f230fd8..7a7c0331 100644 --- a/coretk/coretk/images.py +++ b/coretk/coretk/images.py @@ -46,9 +46,9 @@ class Images: if node_type == core_pb2.NodeType.HUB: return Images.get(ImageEnum.HUB), "hub" if node_type == core_pb2.NodeType.WIRELESS_LAN: - return Images.get(ImageEnum.WLAN.value), "wlan" + return Images.get(ImageEnum.WLAN), "wlan" if node_type == core_pb2.NodeType.EMANE: - return Images.get(ImageEnum.EMANE.value), "emane" + return Images.get(ImageEnum.EMANE), "emane" if node_type == core_pb2.NodeType.RJ45: return Images.get(ImageEnum.RJ45), "rj45" diff --git a/coretk/coretk/switch.png b/coretk/coretk/switch.png deleted file mode 100644 index f8c852947639b68084a32c96f156ec1be99829e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5286 zcmZ{ocQ72>*TevdH;B4-kINfX72sWoH^e)XYSlG_r&V!Y2Kw^p#T5?ceSAE2DgO%JIF|G z=NH=znztaa(a}`D<*l8oeF?t>xhK@b=a&By3V1x|qV%uR&r{Xmf1P82d&B?$eT9~~ zs$sy7?X19L^Y5X%%IiOagR^(?I7SofA0zIIlDXjs30cXbW|>HBBZYe_d&YK*3N4`K zdItt5n1G)RYrkJYlvjY?lZSy86#ZOvQGj76mjuMI9|DC;COmF%Ds|Y-TiEd)3k>(g z@>^3SN}N<)znoWS_Bh_iJIq`>J-y6Dz$^ZX-PH0fq=p|C=@vBEdd(5?`w;&FR!q#5 zB%=2?4O(mrLq>FK^}Gsyv$qg82)A4bH|tGVU!G6%0(FA*&kkwOj1$4FU(mjNhlZqXkQ(X2)u}mYMYO zS$`}{`@84MUubjcRx6RB+UMC8ASzoPEA<`c!2afK(-v#3ImM6S?pH9gp%~7NkVvB- zQZhVXE_LK-kBLG@-pPdm4~oH-vbWs_Mt>Qk*@vPo*7PHF2v$I^f8bN{eNeFAF4n=U zGNF9M+q;~yci~?(6XIkxtZ9}Sd$%8ZH}+%erC^Jgwo@cmXMQUlU`-VZeV1XFN?dMA zmr^Iz>K-JW9W11nGB1%c_}BZbW>Uk}zQ~~wNsDixVuexeOezA z=)b1zK00x&+IJY(I7y_vOiG{%1d&MPhvusY@t}04ke|t;p}jonuKj`~l4zU#^w^MP z^b@fgS0~BvH#Ix7spObK&YQS9rggCy%9pSDF1`)w3TK3P>ORM4u2?&m>>9@ux+ba! zO}PS{WeV==!wsh1u(=8eqB)4CF|QTVUcM2D&q`LCLaJs%1`qWZ%$pJV-p#=^{t*!C z2v1|=R-oX?%^v_=_|dbG*l*s)?6PicZPjbAc!R<0_;yZh2cMR74N`c8dLoa$s$C8x zR7gXTj-Sz6Fi?pPi`WQCGyhm*hCT%w(pYJ!_SAcckoN_sE}gc7?b*-}VFgPpdp6vQ z*H##;<`5qA1=QDk%T28YN* zJJDO0X(61`!buIP>ENUgq5?Ndk!*RbK*JK2idkE}mF4B?nPUgE0 zW-?l&Lf0yxtFp6&tB6p;jaS{pjj;Nz1jqE>r6{s=E)Da#I!T*QFuC;yhxQU7ogc-woTcxzbfl1RGyjE1_P82i#ZM@3@0%J+NqTQpC9JH8LXZt_x%-L z7xjZ3Idvm>qO}4}koklg4VL+>9sniYC5|_apg!}n?L+Gq2dYy@lPvA}c61)Y@#`r~ z43ztwyiE0=oWVQ!alFd%i;C>Bdx6sk4=`rWHjztToh@5k@Xcggsu8k4IX(X&x`OUm z&HC#3wQu@SR758=nW4Og(<{_UV4ZYdg4Ku)bHg2s9F{n&{7_X{lRdQu5^%M zOi~n@qAm<2b(h(`sGLy83i^i4lpbW>9KhWyW~u(rAjU31^+naX@cS~tkdi@0ogDUT zE3luH{h04-P9xF`b`I)JYyCfFc4lVul zjEayDrV_!&E01*$H0qqrQs;eg*=CwW=LJFO4xl_;Df{a^UB84_26EK1LlQM+P~`G5 z-2L3Pb2AyycC&J*_il6PyK{1=D7QJ|Nyw0iPhKkx?HflmPX-8{(en|ciWXu8YlKmp zvrq&k*gfE(wUv%TvNxvLb=MA89MC-g=(@N?DjRo1p4hhKyi2#4q-GXI6KNyf^Xq3J zqA)qkEL|z7cE>`vX6e+!I|mlPD?M&r>;5jJTM>7et8NFIMh$0?;bsX%jphQ%i!Hm3 zbHrIMin969_1|@=Z8iBW%5naOKo?9#6Ylh?NhV`E#%=g!`@2r8ajK$XlyBlw{c$Tz z#5>1(ZnGP4x)x6l=|T8wK4Ft*mYM}12!#kAGQH;|qqY#gw%DVwBd@wsHdCPt*)fC+ zi#5>b(@td?POxM+78k+SnUea>jkd|H8>L~WUEDa{x8$OB?{?|h_NIT5R>)h8HLn_` zlB$h(2{ObBR=;9(N>2qLm#!+sZC0kpA!veY{MTK(U6m}RV3G|MRty830Hc~Z4^f7O z)hEhf=HD6*@C&VLRnDK)SfkPiHD`NnY=kOx^SPF6dU)o~y(L8y(^wjdV7uqMLcmw)aKq=KZejxDc`@^aMI%ZdH z=G=kX(@*xS&WjC8KZy-g+AQQIX;naDaJ;LGLZGgp(dk17mMi$SKn_-dVSc)J>uy@G z(0*f~4BJYSi@5zfKIllqvnbU?L`XiDV|5u(ws9Xj{^_01R=wZLscAaL_e_GtX~sj{ z85Cye*km@l<+->>VP+4rudp|H1{h*KIilVl*q2IRh^umSUm9D}F{Vjc zF85BXx1Ehd8Jro|xKIj{F^k{Z%==XA;+r#J-tI~O>#SFG2GSw!5|;?t)*tEF#wsxC z#?BMCJ&&GH^I@~+*%?LMgDgc<@OsksvMhIhpLd;d z{2tQH-V4pYh#@g$LU|o+4F6r6@4ED8$#?&@-GrNXjs8fg#+S@4>h zl$xyob}5BF5ta4U3QfKEOP0O(HD%By_G=loe(OwVj4G+HY1t|$VcP*~ZNk`r4w3K| zvwQ;n3y{J!l&EW~j#10WNRIi;-}$@AUM%ndQEZ3~r8ziW9yu3LrAVN;7n*-P!uxgA zgs{3iX*xOK@zB~L(g`{>p2=aoJ17>inC}$k08oT^4d=$0U)R-FY4(Ggs-F+$vERX@ zh{2|ts!cde8=M*F*GbNBYSdn9>AQXPuBK*YPEKxiiwjJ%`%@qA%k0faWC^@po_dja}f;=3jO$KH^>T@d1zyBOUeIQiPE|W%ej|W-i~pMPKAp+rXU6 zj)kc9PP_?r$ZB3iLLXVc$0u6Ot2;<^*%~wxT0~zmm6NMl0uNz?U36I$i)5DaTKuqw4Vq?Asc<+VMAv$=F>7e+VQ%%4$gRd_b`@yW) z`{wEt5xq2f^|p>t%zkeF8`~x;FEA#(dbG;&=VLPr_~KB*&zIVhS8=F#Yt;5NY$&%? zX59mfT@)J$Di!}J+>XOKYmA`KZrj=yn*B3}&I0^oD#Qi%h*ZxF{s=X;l5)3(1BkIwFk_ze^y!#E^gVv?E0KME%cq1UwKh_{*;@i7sjotd0TUZazK ziAP6=&NoX>rbYmh8%tjVkB!JA-c0UU-kj=k{7`Nt^-PFSQsT9zNz!`@*GR=I6AxIE;e5WR}4O>TT9VAI|x0sc75wWef6f1 zel1!mlxmHl$Hhh(B%{Ks9X^P7lnpD|uozEk7us?fO>H%;dG({O#^}oi+mom~LaDog zD&^s79$bBHX~&-@n0r+w>n!g&tUv($H7SGr~T`pi4Yqj z_8fa7<&f#I)!Tn>60D!5molAdH<8eA~6`^8}J4UM_~vq!8;_<_jYRmXI+#T=ZAN)s@b1*7Oq=QKj)Bj-9hl5m`h{_H#+#*Ov6(~jQx4< zD<^Z*eg}Ddkw{;;sH`d8`lZ!=we8VxovL$N+~l}iegIF`1m^Ae#A!!Ar$?B$Y<2sm zXb|mVf%>+P(zm`rpZJhu(;}vwe4_7rx~&i3rObxcm92zB8H~G@UlY=gg|1hZhN+(Z z{#2guO;L{nrWA#<>_o+dTvpbi8!f2{W`lOL&i1LTroZvkbbK8)#-T!L>PlRES9(Jq zWQJI_)tqbuC<(c&NZu#+8SN9^Pza6F@ zE<7=FOMp*E{FA$5@9UfPVvxn%$|1JQ&`P|JI8W$g^6j_%1C2+W%mraK4kl`3;v`q)3Y($NXuPYeE(KcqV@p zcr=)hW zA}e_!2OOATv#>g_j7Uh(_1v#7sWNHES@+*wPuT@)=*V@y-umbn0@f6H(Z4@Pc>D2t z@m-qvTfD?+@~|RA#Qy9fwykjU`hZ{*-o&7Q>Z&Qb;~ugo-+p4HS!azwAc+0@g;zgB zv2Vs2f2{rU!${0a%;F~`7#7#HpkyH*l;x=VW+WiPQLg7~hDi9OXi@+30rfa3VkT_< zoegPE*~$fEx;f*{%@k|iirJxT+|8@2d7~~AF`qxjhUGy1 zXn=XXA3GlGM^?hXc{XkzCjG3(WPGg96+Q^@sxVWEG4Q9SP<&cWbaS*X3re@tRcSbG zKK=M~H>%)1Y(ccRMRCn|*TgX%#n|k)DfM+=gxAQjAni*l}sOSv%Mn*jd{KdJWovZ-W3@ M8hYwA5Ua@l0JEh!?f?J) From 0f78acaa0ce4c55bd99a753b93ec37fc3ccb6bc8 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 13:57:41 -0700 Subject: [PATCH 05/12] update method names for drawing main app, moved delete window call into app --- coretk/coretk/app.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/coretk/coretk/app.py b/coretk/coretk/app.py index 72749524..73cbcfbd 100644 --- a/coretk/coretk/app.py +++ b/coretk/coretk/app.py @@ -27,26 +27,27 @@ class Application(tk.Frame): self.adjust_to_dim_var = tk.IntVar(value=0) self.core = CoreClient(self) self.setup_app() - self.create_menu() - self.create_widgets() + self.draw_menu() + self.draw_toolbar() self.draw_canvas() self.core.set_up() def setup_app(self): self.master.title("CORE") self.master.geometry("1000x800") + self.master.protocol("WM_DELETE_WINDOW", self.on_closing) image = Images.get(ImageEnum.CORE) self.master.tk.call("wm", "iconphoto", self.master._w, image) self.pack(fill=tk.BOTH, expand=True) - def create_menu(self): + def draw_menu(self): self.master.option_add("*tearOff", tk.FALSE) self.menubar = tk.Menu(self.master) self.core_menu = CoreMenubar(self, self.master, self.menubar) self.core_menu.create_core_menubar() self.master.config(menu=self.menubar) - def create_widgets(self): + def draw_toolbar(self): edit_frame = tk.Frame(self) edit_frame.pack(side=tk.LEFT, fill=tk.Y, ipadx=2, ipady=2) self.core_editbar = CoreToolbar(self, edit_frame, self.menubar) @@ -86,5 +87,4 @@ class Application(tk.Frame): if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) app = Application() - app.master.protocol("WM_DELETE_WINDOW", app.on_closing) app.mainloop() From f10acbc8d97d096c8ea99e31cc9eaf118180aabc Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 16:31:40 -0700 Subject: [PATCH 06/12] added gui directory check and creation, created module for referencing gui directories --- coretk/coretk/app.py | 2 + coretk/coretk/appdirs.py | 39 ++++++++++++++++++ .../{wallpaper => backgrounds}/sample1-bg.gif | Bin .../{wallpaper => backgrounds}/sample4-bg.jpg | Bin coretk/coretk/images.py | 12 ++---- coretk/coretk/setwallpaper.py | 7 +--- 6 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 coretk/coretk/appdirs.py rename coretk/coretk/{wallpaper => backgrounds}/sample1-bg.gif (100%) rename coretk/coretk/{wallpaper => backgrounds}/sample4-bg.jpg (100%) diff --git a/coretk/coretk/app.py b/coretk/coretk/app.py index 73cbcfbd..671504a8 100644 --- a/coretk/coretk/app.py +++ b/coretk/coretk/app.py @@ -1,6 +1,7 @@ import logging import tkinter as tk +from coretk import appdirs from coretk.coreclient import CoreClient from coretk.coremenubar import CoreMenubar from coretk.coretoolbar import CoreToolbar @@ -86,5 +87,6 @@ class Application(tk.Frame): if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) + appdirs.check_directory() app = Application() app.mainloop() diff --git a/coretk/coretk/appdirs.py b/coretk/coretk/appdirs.py new file mode 100644 index 00000000..7dae4bf3 --- /dev/null +++ b/coretk/coretk/appdirs.py @@ -0,0 +1,39 @@ +import logging +import shutil +from pathlib import Path + +# gui home paths +HOME_PATH = Path.home().joinpath(".coretk") +BACKGROUNDS_PATH = HOME_PATH.joinpath("backgrounds") +CUSTOM_EMANE_PATH = HOME_PATH.joinpath("custom_emane") +CUSTOM_SERVICE_PATH = HOME_PATH.joinpath("custom_services") +ICONS_PATH = HOME_PATH.joinpath("icons") +MOBILITY_PATH = HOME_PATH.joinpath("mobility") +XML_PATH = HOME_PATH.joinpath("xml") +CONFIG_PATH = HOME_PATH.joinpath("gui.yaml") + +# local paths +LOCAL_ICONS_PATH = Path(__file__).parent.joinpath("icons").absolute() +LOCAL_BACKGROUND_PATH = Path(__file__).parent.joinpath("backgrounds").absolute() + + +def check_directory(): + if HOME_PATH.exists(): + logging.info("~/.coretk exists") + return + logging.info("creating ~/.coretk") + HOME_PATH.mkdir() + BACKGROUNDS_PATH.mkdir() + CUSTOM_EMANE_PATH.mkdir() + CUSTOM_SERVICE_PATH.mkdir() + ICONS_PATH.mkdir() + MOBILITY_PATH.mkdir() + XML_PATH.mkdir() + for image in LOCAL_ICONS_PATH.glob("*"): + new_image = ICONS_PATH.joinpath(image.name) + shutil.copy(image, new_image) + for background in LOCAL_BACKGROUND_PATH.glob("*"): + new_background = BACKGROUNDS_PATH.joinpath(background.name) + shutil.copy(background, new_background) + with CONFIG_PATH.open("w") as f: + f.write("# gui config") diff --git a/coretk/coretk/wallpaper/sample1-bg.gif b/coretk/coretk/backgrounds/sample1-bg.gif similarity index 100% rename from coretk/coretk/wallpaper/sample1-bg.gif rename to coretk/coretk/backgrounds/sample1-bg.gif diff --git a/coretk/coretk/wallpaper/sample4-bg.jpg b/coretk/coretk/backgrounds/sample4-bg.jpg similarity index 100% rename from coretk/coretk/wallpaper/sample4-bg.jpg rename to coretk/coretk/backgrounds/sample4-bg.jpg diff --git a/coretk/coretk/images.py b/coretk/coretk/images.py index 7a7c0331..f9b5f870 100644 --- a/coretk/coretk/images.py +++ b/coretk/coretk/images.py @@ -1,13 +1,10 @@ import logging -import os from enum import Enum from PIL import Image, ImageTk from core.api.grpc import core_pb2 - -PATH = os.path.abspath(os.path.dirname(__file__)) -ICONS_DIR = os.path.join(PATH, "icons") +from coretk.appdirs import LOCAL_ICONS_PATH class Images: @@ -15,14 +12,11 @@ class Images: @classmethod def load_all(cls): - for file_name in os.listdir(ICONS_DIR): - file_path = os.path.join(ICONS_DIR, file_name) - name = file_name.split(".")[0] - cls.load(name, file_path) + for image in LOCAL_ICONS_PATH.glob("*"): + cls.load(image.stem, str(image)) @classmethod def load(cls, name, file_path): - # file_path = os.path.join(PATH, file_path) image = Image.open(file_path) tk_image = ImageTk.PhotoImage(image) cls.images[name] = tk_image diff --git a/coretk/coretk/setwallpaper.py b/coretk/coretk/setwallpaper.py index edace83c..81932208 100644 --- a/coretk/coretk/setwallpaper.py +++ b/coretk/coretk/setwallpaper.py @@ -3,14 +3,12 @@ set wallpaper """ import enum import logging -import os import tkinter as tk from tkinter import filedialog from PIL import Image, ImageTk -PATH = os.path.abspath(os.path.dirname(__file__)) -WALLPAPER_DIR = os.path.join(PATH, "wallpaper") +from coretk.appdirs import BACKGROUNDS_PATH class ScaleOption(enum.Enum): @@ -60,7 +58,7 @@ class CanvasWallpaper: def open_image_link(self): filename = filedialog.askopenfilename( - initialdir=WALLPAPER_DIR, + initialdir=str(BACKGROUNDS_PATH), title="Open", filetypes=( ("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."), @@ -207,7 +205,6 @@ class CanvasWallpaper: cropy = img_h = tk_img.height() if img_w > canvas_w: - cropx -= img_w - canvas_w if img_h > canvas_h: cropy -= img_h - canvas_h From b4f4ecd93d56157dbb29026a45e0bdf10f81a23c Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 16:47:30 -0700 Subject: [PATCH 07/12] avoid issues when open/save xml provides no value --- coretk/coretk/menuaction.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/coretk/coretk/menuaction.py b/coretk/coretk/menuaction.py index 7598f210..bfbb5c5d 100644 --- a/coretk/coretk/menuaction.py +++ b/coretk/coretk/menuaction.py @@ -7,13 +7,12 @@ import webbrowser from tkinter import filedialog, messagebox from core.api.grpc import core_pb2 +from coretk.appdirs import XML_PATH from coretk.dialogs.sessionoptions import SessionOptionsDialog from coretk.dialogs.sessions import SessionsDialog from coretk.setwallpaper import CanvasWallpaper from coretk.sizeandscale import SizeAndScale -SAVEDIR = "/home/ncs/Desktop/" - def sub_menu_items(): logging.debug("Click on sub menu items") @@ -361,24 +360,26 @@ class MenuAction: def file_save_as_xml(self): logging.info("menuaction.py file_save_as_xml()") file_path = filedialog.asksaveasfilename( - initialdir=SAVEDIR, + initialdir=str(XML_PATH), title="Save As", filetypes=(("EmulationScript XML files", "*.xml"), ("All files", "*")), defaultextension=".xml", ) - self.app.core.save_xml(file_path) + if file_path: + self.app.core.save_xml(file_path) def file_open_xml(self): logging.info("menuaction.py file_open_xml()") self.app.is_open_xml = True file_path = filedialog.askopenfilename( - initialdir=SAVEDIR, + initialdir=str(XML_PATH), title="Open", filetypes=(("EmulationScript XML File", "*.xml"), ("All Files", "*")), ) - # clean up before opening a new session - self.prompt_save_running_session() - self.app.core.open_xml(file_path) + if file_path: + logging.info("opening xml: %s", file_path) + self.prompt_save_running_session() + self.app.core.open_xml(file_path) # Todo might not need # self.application.core_editbar.destroy_children_widgets() From 09e18889b0605b4c0ded372ffa766bdb0c3cfb8c Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Fri, 1 Nov 2019 18:14:36 -0700 Subject: [PATCH 08/12] start to hooks dialog and hook dialog create/edit --- coretk/coretk/coremenubar.py | 2 +- coretk/coretk/dialogs/hooks.py | 106 +++++++++++++++++++++++++++++++++ coretk/coretk/menuaction.py | 10 ++-- 3 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 coretk/coretk/dialogs/hooks.py diff --git a/coretk/coretk/coremenubar.py b/coretk/coretk/coremenubar.py index 7b3f2633..0751ee06 100644 --- a/coretk/coretk/coremenubar.py +++ b/coretk/coretk/coremenubar.py @@ -607,7 +607,7 @@ class CoreMenubar(object): label="Comments...", command=action.session_comments, underline=0 ) session_menu.add_command( - label="Hooks...", command=action.session_hooks, underline=0 + label="Hooks...", command=self.menu_action.session_hooks, underline=0 ) session_menu.add_command( label="Reset node positions", diff --git a/coretk/coretk/dialogs/hooks.py b/coretk/coretk/dialogs/hooks.py new file mode 100644 index 00000000..bdf96d33 --- /dev/null +++ b/coretk/coretk/dialogs/hooks.py @@ -0,0 +1,106 @@ +import tkinter as tk +from tkinter import ttk + +from core.api.grpc import core_pb2 +from coretk.dialogs.dialog import Dialog + + +class HookDialog(Dialog): + def __init__(self, master, app): + super().__init__(master, app, "Hook", modal=True) + self.name = tk.StringVar() + self.data = None + self.hook = None + self.draw() + + def draw(self): + self.columnconfigure(0, weight=1) + + # name and states + frame = tk.Frame(self) + frame.grid(row=0, sticky="ew", pady=2) + frame.columnconfigure(0, weight=2) + frame.columnconfigure(1, weight=7) + frame.columnconfigure(2, weight=1) + label = tk.Label(frame, text="Name") + label.grid(row=0, column=0, sticky="ew") + entry = tk.Entry(frame, textvariable=self.name) + entry.grid(row=0, column=1, sticky="ew") + combobox = ttk.Combobox(frame, values=("DEFINITION", "CONFIGURATION")) + combobox.grid(row=0, column=2, sticky="ew") + + # data + self.data = tk.Text(self) + self.data.grid(row=1, sticky="nsew", pady=2) + + # button row + frame = tk.Frame(self) + frame.grid(row=2, sticky="ew", pady=2) + for i in range(2): + frame.columnconfigure(i, weight=1) + button = tk.Button(frame, text="Save", command=lambda: self.save()) + button.grid(row=0, column=0, sticky="ew") + button = tk.Button(frame, text="Cancel", command=lambda: self.destroy()) + button.grid(row=0, column=1, sticky="ew") + + def set(self, hook): + self.hook = hook + self.name.set(hook.file) + self.data.delete(1.0, tk.END) + self.data.insert(tk.END, hook.data) + + def save(self): + data = self.data.get("1.0", tk.END).strip() + self.hook = core_pb2.Hook(file=self.name.get(), data=data) + self.destroy() + + +class HooksDialog(Dialog): + def __init__(self, master, app): + super().__init__(master, app, "Hooks", modal=True) + self.listbox = None + self.edit = None + self.delete = None + self.selected = None + self.hooks = {} + self.draw() + + def draw(self): + self.columnconfigure(0, weight=1) + self.listbox = tk.Listbox(self) + self.listbox.grid(row=0, sticky="ew") + self.listbox.bind("<>", self.select) + frame = tk.Frame(self) + frame.grid(row=1, sticky="ew") + for i in range(4): + frame.columnconfigure(i, weight=1) + button = tk.Button(frame, text="Create", command=self.click_create) + button.grid(row=0, column=0, sticky="ew") + self.edit = tk.Button( + frame, text="Edit", state=tk.DISABLED, command=self.click_edit + ) + self.edit.grid(row=0, column=1, sticky="ew") + self.delete = tk.Button(frame, text="Delete", state=tk.DISABLED) + self.delete.grid(row=0, column=2, sticky="ew") + button = tk.Button(frame, text="Cancel", command=lambda: self.destroy()) + button.grid(row=0, column=3, sticky="ew") + + def click_create(self): + dialog = HookDialog(self, self.app) + dialog.show() + hook = dialog.hook + if hook: + self.hooks[hook.file] = hook + self.listbox.insert(tk.END, hook.file) + + def click_edit(self): + hook = self.hooks[self.selected] + dialog = HookDialog(self, self.app) + dialog.set(hook) + dialog.show() + + def select(self, event): + self.edit.config(state=tk.NORMAL) + self.delete.config(state=tk.NORMAL) + index = self.listbox.curselection()[0] + self.selected = self.listbox.get(index) diff --git a/coretk/coretk/menuaction.py b/coretk/coretk/menuaction.py index bfbb5c5d..64caf8ae 100644 --- a/coretk/coretk/menuaction.py +++ b/coretk/coretk/menuaction.py @@ -8,6 +8,7 @@ from tkinter import filedialog, messagebox from core.api.grpc import core_pb2 from coretk.appdirs import XML_PATH +from coretk.dialogs.hooks import HooksDialog from coretk.dialogs.sessionoptions import SessionOptionsDialog from coretk.dialogs.sessions import SessionsDialog from coretk.setwallpaper import CanvasWallpaper @@ -299,10 +300,6 @@ def session_comments(): logging.debug("Click session comments") -def session_hooks(): - logging.debug("Click session hooks") - - def session_reset_node_positions(): logging.debug("Click session reset node positions") @@ -406,3 +403,8 @@ class MenuAction: logging.debug("Click session change sessions") dialog = SessionsDialog(self.app, self.app) dialog.show() + + def session_hooks(self): + logging.debug("Click session hooks") + dialog = HooksDialog(self.app, self.app) + dialog.show() From c947d8c6c240f6329cc9d9e1a8f3642ad05d68e1 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Sat, 2 Nov 2019 10:29:16 -0700 Subject: [PATCH 09/12] update to hooks dialog to leverage grpc, allows for getting hooks and creation --- coretk/coretk/dialogs/hooks.py | 67 +++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/coretk/coretk/dialogs/hooks.py b/coretk/coretk/dialogs/hooks.py index bdf96d33..a4195246 100644 --- a/coretk/coretk/dialogs/hooks.py +++ b/coretk/coretk/dialogs/hooks.py @@ -1,3 +1,4 @@ +import logging import tkinter as tk from tkinter import ttk @@ -11,10 +12,12 @@ class HookDialog(Dialog): self.name = tk.StringVar() self.data = None self.hook = None + self.state = tk.StringVar() self.draw() def draw(self): self.columnconfigure(0, weight=1) + self.rowconfigure(1, weight=1) # name and states frame = tk.Frame(self) @@ -26,12 +29,33 @@ class HookDialog(Dialog): label.grid(row=0, column=0, sticky="ew") entry = tk.Entry(frame, textvariable=self.name) entry.grid(row=0, column=1, sticky="ew") - combobox = ttk.Combobox(frame, values=("DEFINITION", "CONFIGURATION")) + values = tuple(x for x in core_pb2.SessionState.Enum.keys() if x != "NONE") + initial_state = core_pb2.SessionState.Enum.Name(core_pb2.SessionState.RUNTIME) + self.state.set(initial_state) + self.name.set(f"{initial_state.lower()}_hook.sh") + combobox = ttk.Combobox(frame, textvariable=self.state, values=values) combobox.grid(row=0, column=2, sticky="ew") + combobox.bind("<>", self.state_change) # data - self.data = tk.Text(self) - self.data.grid(row=1, sticky="nsew", pady=2) + frame = tk.Frame(self) + frame.columnconfigure(0, weight=1) + frame.rowconfigure(0, weight=1) + frame.grid(row=1, sticky="nsew", pady=2) + self.data = tk.Text(frame) + self.data.insert( + 1.0, + ( + "#!/bin/sh\n" + "# session hook script; write commands here to execute on the host at the\n" + "# specified state\n" + ), + ) + self.data.grid(row=0, column=0, sticky="nsew") + scrollbar = tk.Scrollbar(frame) + scrollbar.grid(row=0, column=1, sticky="ns") + self.data.config(yscrollcommand=scrollbar.set) + scrollbar.config(command=self.data.yview) # button row frame = tk.Frame(self) @@ -43,15 +67,26 @@ class HookDialog(Dialog): button = tk.Button(frame, text="Cancel", command=lambda: self.destroy()) button.grid(row=0, column=1, sticky="ew") + def state_change(self, event): + state_name = self.state.get() + self.name.set(f"{state_name.lower()}_hook.sh") + def set(self, hook): self.hook = hook self.name.set(hook.file) self.data.delete(1.0, tk.END) self.data.insert(tk.END, hook.data) + state_name = core_pb2.SessionState.Enum.Name(hook.state) + self.state.set(state_name) def save(self): data = self.data.get("1.0", tk.END).strip() - self.hook = core_pb2.Hook(file=self.name.get(), data=data) + state_value = core_pb2.SessionState.Enum.Value(self.state.get()) + self.hook = core_pb2.Hook(state=state_value, file=self.name.get(), data=data) + response = self.app.core.client.add_hook( + self.app.core.session_id, self.hook.state, self.hook.file, self.hook.data + ) + logging.info("add hook: %s", response) self.destroy() @@ -59,29 +94,35 @@ class HooksDialog(Dialog): def __init__(self, master, app): super().__init__(master, app, "Hooks", modal=True) self.listbox = None - self.edit = None - self.delete = None + self.edit_button = None + self.delete_button = None self.selected = None self.hooks = {} self.draw() def draw(self): + response = self.app.core.client.get_hooks(self.app.core.session_id) + logging.info("get hooks: %s", response) self.columnconfigure(0, weight=1) + self.rowconfigure(0, weight=1) self.listbox = tk.Listbox(self) - self.listbox.grid(row=0, sticky="ew") + self.listbox.grid(row=0, sticky="nsew") self.listbox.bind("<>", self.select) + for hook in response.hooks: + self.hooks[hook.file] = hook + self.listbox.insert(tk.END, hook.file) frame = tk.Frame(self) frame.grid(row=1, sticky="ew") for i in range(4): frame.columnconfigure(i, weight=1) button = tk.Button(frame, text="Create", command=self.click_create) button.grid(row=0, column=0, sticky="ew") - self.edit = tk.Button( + self.edit_button = tk.Button( frame, text="Edit", state=tk.DISABLED, command=self.click_edit ) - self.edit.grid(row=0, column=1, sticky="ew") - self.delete = tk.Button(frame, text="Delete", state=tk.DISABLED) - self.delete.grid(row=0, column=2, sticky="ew") + self.edit_button.grid(row=0, column=1, sticky="ew") + self.delete_button = tk.Button(frame, text="Delete", state=tk.DISABLED) + self.delete_button.grid(row=0, column=2, sticky="ew") button = tk.Button(frame, text="Cancel", command=lambda: self.destroy()) button.grid(row=0, column=3, sticky="ew") @@ -100,7 +141,7 @@ class HooksDialog(Dialog): dialog.show() def select(self, event): - self.edit.config(state=tk.NORMAL) - self.delete.config(state=tk.NORMAL) + self.edit_button.config(state=tk.NORMAL) + self.delete_button.config(state=tk.NORMAL) index = self.listbox.curselection()[0] self.selected = self.listbox.get(index) From 8c1b70822e1fb0ff987b3c2db102593eb1d604e4 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Sat, 2 Nov 2019 14:34:00 -0700 Subject: [PATCH 10/12] fixed how hooks get created and sent to grpc StartSession, also query hooks when joining a session --- coretk/coretk/coreclient.py | 35 +++++++++++++++++++++++----------- coretk/coretk/dialogs/hooks.py | 23 ++++++++-------------- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py index e5ba838e..ad912422 100644 --- a/coretk/coretk/coreclient.py +++ b/coretk/coretk/coreclient.py @@ -71,6 +71,7 @@ class CoreClient: # data for managing the current session self.nodes = {} self.edges = {} + self.hooks = {} self.id = 1 self.reusable = [] self.preexisting = set() @@ -97,19 +98,30 @@ class CoreClient: ) def join_session(self, session_id): - # query session and set as current session + # update session and title self.session_id = session_id - response = self.client.get_session(self.session_id) - logging.info("joining session(%s): %s", self.session_id, response) - self.client.events(self.session_id, self.handle_events) - - # set title to session self.master.title(f"CORE Session({self.session_id})") - # determine next node id and reusable nodes - session = response.session + # clear session data self.reusable.clear() self.preexisting.clear() + self.nodes.clear() + self.edges.clear() + self.hooks.clear() + + # get session data + response = self.client.get_session(self.session_id) + logging.info("joining session(%s): %s", self.session_id, response) + session = response.session + self.client.events(self.session_id, self.handle_events) + + # get hooks + response = self.client.get_hooks(self.session_id) + logging.info("joined session hooks: %s", response) + for hook in response.hooks: + self.hooks[hook.file] = hook + + # determine next node id and reusable nodes max_id = 1 for node in session.nodes: if node.id > max_id: @@ -262,9 +274,10 @@ class CoreClient: mobility_configs=None, ): response = self.client.start_session( - session_id=self.session_id, - nodes=nodes, - links=links, + self.session_id, + nodes, + links, + hooks=list(self.hooks.values()), wlan_configs=wlan_configs, ) logging.debug("Start session %s, result: %s", self.session_id, response.result) diff --git a/coretk/coretk/dialogs/hooks.py b/coretk/coretk/dialogs/hooks.py index a4195246..7e1338ad 100644 --- a/coretk/coretk/dialogs/hooks.py +++ b/coretk/coretk/dialogs/hooks.py @@ -1,4 +1,3 @@ -import logging import tkinter as tk from tkinter import ttk @@ -11,7 +10,7 @@ class HookDialog(Dialog): super().__init__(master, app, "Hook", modal=True) self.name = tk.StringVar() self.data = None - self.hook = None + self.hook = core_pb2.Hook() self.state = tk.StringVar() self.draw() @@ -82,11 +81,9 @@ class HookDialog(Dialog): def save(self): data = self.data.get("1.0", tk.END).strip() state_value = core_pb2.SessionState.Enum.Value(self.state.get()) - self.hook = core_pb2.Hook(state=state_value, file=self.name.get(), data=data) - response = self.app.core.client.add_hook( - self.app.core.session_id, self.hook.state, self.hook.file, self.hook.data - ) - logging.info("add hook: %s", response) + self.hook.file = self.name.get() + self.hook.data = data + self.hook.state = state_value self.destroy() @@ -97,20 +94,16 @@ class HooksDialog(Dialog): self.edit_button = None self.delete_button = None self.selected = None - self.hooks = {} self.draw() def draw(self): - response = self.app.core.client.get_hooks(self.app.core.session_id) - logging.info("get hooks: %s", response) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self.listbox = tk.Listbox(self) self.listbox.grid(row=0, sticky="nsew") self.listbox.bind("<>", self.select) - for hook in response.hooks: - self.hooks[hook.file] = hook - self.listbox.insert(tk.END, hook.file) + for hook_file in self.app.core.hooks: + self.listbox.insert(tk.END, hook_file) frame = tk.Frame(self) frame.grid(row=1, sticky="ew") for i in range(4): @@ -131,11 +124,11 @@ class HooksDialog(Dialog): dialog.show() hook = dialog.hook if hook: - self.hooks[hook.file] = hook + self.app.core.hooks[hook.file] = hook self.listbox.insert(tk.END, hook.file) def click_edit(self): - hook = self.hooks[self.selected] + hook = self.app.core.hooks[self.selected] dialog = HookDialog(self, self.app) dialog.set(hook) dialog.show() From b991dc0242387b4b9f17b519777983f3e3a3641f Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Sat, 2 Nov 2019 14:46:30 -0700 Subject: [PATCH 11/12] updates to handle delete hook and button states --- coretk/coretk/dialogs/hooks.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/coretk/coretk/dialogs/hooks.py b/coretk/coretk/dialogs/hooks.py index 7e1338ad..95ca8af7 100644 --- a/coretk/coretk/dialogs/hooks.py +++ b/coretk/coretk/dialogs/hooks.py @@ -114,7 +114,9 @@ class HooksDialog(Dialog): frame, text="Edit", state=tk.DISABLED, command=self.click_edit ) self.edit_button.grid(row=0, column=1, sticky="ew") - self.delete_button = tk.Button(frame, text="Delete", state=tk.DISABLED) + self.delete_button = tk.Button( + frame, text="Delete", state=tk.DISABLED, command=self.click_delete + ) self.delete_button.grid(row=0, column=2, sticky="ew") button = tk.Button(frame, text="Cancel", command=lambda: self.destroy()) button.grid(row=0, column=3, sticky="ew") @@ -133,8 +135,19 @@ class HooksDialog(Dialog): dialog.set(hook) dialog.show() + def click_delete(self): + del self.app.core.hooks[self.selected] + self.listbox.delete(tk.ANCHOR) + self.edit_button.config(state=tk.DISABLED) + self.delete_button.config(state=tk.DISABLED) + def select(self, event): - self.edit_button.config(state=tk.NORMAL) - self.delete_button.config(state=tk.NORMAL) - index = self.listbox.curselection()[0] - self.selected = self.listbox.get(index) + if self.listbox.curselection(): + index = self.listbox.curselection()[0] + self.selected = self.listbox.get(index) + self.edit_button.config(state=tk.NORMAL) + self.delete_button.config(state=tk.NORMAL) + else: + self.selected = None + self.edit_button.config(state=tk.DISABLED) + self.delete_button.config(state=tk.DISABLED) From d4f77a01e30c559f765a29fc98648a85701ef8f0 Mon Sep 17 00:00:00 2001 From: bharnden <32446120+bharnden@users.noreply.github.com> Date: Sat, 2 Nov 2019 23:47:43 -0700 Subject: [PATCH 12/12] moved all modules creating dialogs under dialogs package, updated node config and node icon dialogs to use common dialog class, fixed common dialog class show order to fix delayed cases with grab_set --- coretk/coretk/canvasaction.py | 8 +- coretk/coretk/dialogs/dialog.py | 5 +- coretk/coretk/dialogs/nodeconfig.py | 94 ++++++++++ coretk/coretk/dialogs/nodeicon.py | 69 ++++++++ coretk/coretk/{ => dialogs}/nodeservice.py | 0 coretk/coretk/{ => dialogs}/setwallpaper.py | 0 coretk/coretk/{ => dialogs}/sizeandscale.py | 2 +- .../wlanconfig.py} | 13 +- coretk/coretk/imagemodification.py | 91 ---------- coretk/coretk/images.py | 8 +- coretk/coretk/menuaction.py | 4 +- coretk/coretk/nodeconfigtable.py | 164 ------------------ 12 files changed, 184 insertions(+), 274 deletions(-) create mode 100644 coretk/coretk/dialogs/nodeconfig.py create mode 100644 coretk/coretk/dialogs/nodeicon.py rename coretk/coretk/{ => dialogs}/nodeservice.py (100%) rename coretk/coretk/{ => dialogs}/setwallpaper.py (100%) rename coretk/coretk/{ => dialogs}/sizeandscale.py (99%) rename coretk/coretk/{wlanconfiguration.py => dialogs/wlanconfig.py} (97%) delete mode 100644 coretk/coretk/imagemodification.py delete mode 100644 coretk/coretk/nodeconfigtable.py diff --git a/coretk/coretk/canvasaction.py b/coretk/coretk/canvasaction.py index 0c56d4ba..b5f09333 100644 --- a/coretk/coretk/canvasaction.py +++ b/coretk/coretk/canvasaction.py @@ -5,8 +5,8 @@ canvas graph action # import tkinter as tk from core.api.grpc import core_pb2 -from coretk.nodeconfigtable import NodeConfig -from coretk.wlanconfiguration import WlanConfiguration +from coretk.dialogs.nodeconfig import NodeConfigDialog +from coretk.dialogs.wlanconfig import WlanConfiguration # TODO, finish classifying node types NODE_TO_TYPE = { @@ -18,7 +18,6 @@ NODE_TO_TYPE = { class CanvasAction: def __init__(self, master, canvas): self.master = master - self.canvas = canvas self.node_to_show_config = None @@ -31,7 +30,8 @@ class CanvasAction: self.display_wlan_configuration(canvas_node) def display_node_configuration(self): - NodeConfig(self.canvas, self.node_to_show_config) + dialog = NodeConfigDialog(self.master, self.master, self.node_to_show_config) + dialog.show() self.node_to_show_config = None def display_wlan_configuration(self, canvas_node): diff --git a/coretk/coretk/dialogs/dialog.py b/coretk/coretk/dialogs/dialog.py index b218d8c7..f9cfcabe 100644 --- a/coretk/coretk/dialogs/dialog.py +++ b/coretk/coretk/dialogs/dialog.py @@ -17,8 +17,9 @@ class Dialog(tk.Toplevel): def show(self): self.transient(self.master) self.focus_force() - if self.modal: - self.grab_set() self.update() self.deiconify() + if self.modal: + self.wait_visibility() + self.grab_set() self.wait_window() diff --git a/coretk/coretk/dialogs/nodeconfig.py b/coretk/coretk/dialogs/nodeconfig.py new file mode 100644 index 00000000..d670853c --- /dev/null +++ b/coretk/coretk/dialogs/nodeconfig.py @@ -0,0 +1,94 @@ +import tkinter as tk +from tkinter import ttk + +from coretk.dialogs.dialog import Dialog +from coretk.dialogs.nodeicon import NodeIconDialog +from coretk.dialogs.nodeservice import NodeServices + +NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"] +DEFAULTNODES = ["router", "host", "PC"] + + +class NodeConfigDialog(Dialog): + def __init__(self, master, app, canvas_node): + """ + create an instance of node configuration + + :param master: dialog master + :param coretk.app.Application: main app + :param coretk.graph.CanvasNode canvas_node: canvas node object + """ + super().__init__(master, app, f"{canvas_node.name} Configuration", modal=True) + self.canvas_node = canvas_node + self.image = canvas_node.image + self.image_button = None + self.name = tk.StringVar(value=canvas_node.name) + self.type = tk.StringVar(value=canvas_node.node_type) + self.server = tk.StringVar() + self.draw() + + def draw(self): + self.columnconfigure(0, weight=1) + self.draw_first_row() + self.draw_second_row() + self.draw_third_row() + + def draw_first_row(self): + frame = tk.Frame(self) + frame.grid(row=0, column=0, pady=2, sticky="ew") + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + frame.columnconfigure(2, weight=1) + + entry = tk.Entry(frame, textvariable=self.name) + entry.grid(row=0, column=0, padx=2, sticky="ew") + + combobox = ttk.Combobox(frame, textvariable=self.type, values=DEFAULTNODES) + combobox.grid(row=0, column=1, padx=2, sticky="ew") + + combobox = ttk.Combobox(frame, textvariable=self.server, values=["localhost"]) + combobox.current(0) + combobox.grid(row=0, column=2, sticky="ew") + + def draw_second_row(self): + frame = tk.Frame(self) + frame.grid(row=1, column=0, pady=2, sticky="ew") + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + + button = tk.Button(frame, text="Services", command=lambda: NodeServices()) + button.grid(row=0, column=0, padx=2, sticky="ew") + + self.image_button = tk.Button( + frame, + text="Icon", + image=self.image, + compound=tk.LEFT, + command=self.click_icon, + ) + self.image_button.grid(row=0, column=1, sticky="ew") + + def draw_third_row(self): + frame = tk.Frame(self) + frame.grid(row=2, column=0, sticky="ew") + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + + button = tk.Button(frame, text="Apply", command=self.config_apply) + button.grid(row=0, column=0, padx=2, sticky="ew") + + button = tk.Button(frame, text="Cancel", command=self.destroy) + button.grid(row=0, column=1, sticky="ew") + + def click_icon(self): + dialog = NodeIconDialog(self, self.app, self.canvas_node) + dialog.show() + if dialog.image: + self.image = dialog.image + self.image_button.config(image=self.image) + + def config_apply(self): + self.canvas_node.name = self.name.get() + self.canvas_node.image = self.image + self.canvas_node.canvas.itemconfig(self.canvas_node.id, image=self.image) + self.destroy() diff --git a/coretk/coretk/dialogs/nodeicon.py b/coretk/coretk/dialogs/nodeicon.py new file mode 100644 index 00000000..d82c0756 --- /dev/null +++ b/coretk/coretk/dialogs/nodeicon.py @@ -0,0 +1,69 @@ +import tkinter as tk +from tkinter import filedialog + +from coretk.appdirs import ICONS_PATH +from coretk.dialogs.dialog import Dialog +from coretk.images import Images + + +class NodeIconDialog(Dialog): + def __init__(self, master, app, canvas_node): + """ + create an instance of ImageModification + :param master: dialog master + :param coretk.app.Application: main app + :param coretk.graph.CanvasNode canvas_node: node object + """ + super().__init__(master, app, f"{canvas_node.name} Icon", modal=True) + self.file_path = tk.StringVar() + self.image_label = None + self.image = canvas_node.image + self.draw() + + def draw(self): + self.columnconfigure(0, weight=1) + + # row one + frame = tk.Frame(self) + frame.grid(row=0, column=0, pady=2, sticky="ew") + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=3) + label = tk.Label(frame, text="Image") + label.grid(row=0, column=0, sticky="ew") + entry = tk.Entry(frame, textvariable=self.file_path) + entry.grid(row=0, column=1, sticky="ew") + button = tk.Button(frame, text="...", command=self.click_file) + button.grid(row=0, column=2) + + # row two + self.image_label = tk.Label(self, image=self.image) + self.image_label.grid(row=1, column=0, pady=2, sticky="ew") + + # row three + frame = tk.Frame(self) + frame.grid(row=2, column=0, sticky="ew") + frame.columnconfigure(0, weight=1) + frame.columnconfigure(1, weight=1) + button = tk.Button(frame, text="Apply", command=self.destroy) + button.grid(row=0, column=0, sticky="ew") + + button = tk.Button(frame, text="Cancel", command=self.click_cancel) + button.grid(row=0, column=1, sticky="ew") + + def click_file(self): + file_path = filedialog.askopenfilename( + initialdir=str(ICONS_PATH), + title="Open", + filetypes=( + ("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."), + ("All Files", "*"), + ), + ) + if file_path: + self.image = Images.create(file_path) + self.image_label.config(image=self.image) + self.file_path.set(file_path) + + def click_cancel(self): + self.image = None + self.destroy() diff --git a/coretk/coretk/nodeservice.py b/coretk/coretk/dialogs/nodeservice.py similarity index 100% rename from coretk/coretk/nodeservice.py rename to coretk/coretk/dialogs/nodeservice.py diff --git a/coretk/coretk/setwallpaper.py b/coretk/coretk/dialogs/setwallpaper.py similarity index 100% rename from coretk/coretk/setwallpaper.py rename to coretk/coretk/dialogs/setwallpaper.py diff --git a/coretk/coretk/sizeandscale.py b/coretk/coretk/dialogs/sizeandscale.py similarity index 99% rename from coretk/coretk/sizeandscale.py rename to coretk/coretk/dialogs/sizeandscale.py index 5c746c39..0267a300 100644 --- a/coretk/coretk/sizeandscale.py +++ b/coretk/coretk/dialogs/sizeandscale.py @@ -4,7 +4,7 @@ size and scale import tkinter as tk from functools import partial -from coretk.setwallpaper import ScaleOption +from coretk.dialogs.setwallpaper import ScaleOption DRAW_OBJECT_TAGS = ["edge", "node", "nodename", "linkinfo", "antenna"] diff --git a/coretk/coretk/wlanconfiguration.py b/coretk/coretk/dialogs/wlanconfig.py similarity index 97% rename from coretk/coretk/wlanconfiguration.py rename to coretk/coretk/dialogs/wlanconfig.py index 32bb56e2..8065a5fa 100644 --- a/coretk/coretk/wlanconfiguration.py +++ b/coretk/coretk/dialogs/wlanconfig.py @@ -5,7 +5,7 @@ wlan configuration import tkinter as tk from functools import partial -from coretk.imagemodification import ImageModification +from coretk.dialogs.nodeicon import NodeIconDialog class WlanConfiguration: @@ -57,16 +57,13 @@ class WlanConfiguration: e.grid(row=0, column=1, padx=3, pady=3) b = tk.Button(f, text="None") b.grid(row=0, column=2, padx=3, pady=3) - b = tk.Button( - f, - image=self.image, - command=lambda: ImageModification( - canvas=self.canvas, canvas_node=self.canvas_node, node_config=self - ), - ) + b = tk.Button(f, image=self.image, command=lambda: self.click_image) b.grid(row=0, column=3, padx=3, pady=3) f.grid(padx=2, pady=2, ipadx=2, ipady=2) + def click_image(self): + NodeIconDialog(self.app, canvas_node=self.canvas_node, node_config=self) + def create_string_var(self, val): """ create string variable for convenience diff --git a/coretk/coretk/imagemodification.py b/coretk/coretk/imagemodification.py deleted file mode 100644 index 646f31b7..00000000 --- a/coretk/coretk/imagemodification.py +++ /dev/null @@ -1,91 +0,0 @@ -""" -node image modification -""" - - -import os -import tkinter as tk -from tkinter import filedialog - -from PIL import Image, ImageTk - -PATH = os.path.abspath(os.path.dirname(__file__)) -ICONS_DIR = os.path.join(PATH, "icons") - - -class ImageModification: - def __init__(self, canvas, canvas_node, node_config): - """ - create an instance of ImageModification - :param coretk.graph.CanvasGraph canvas: canvas object - :param coretk.graph.CanvasNode canvas_node: node object - :param coretk.nodeconfigtable.NodeConfig node_config: node configuration object - """ - self.canvas = canvas - self.image = canvas_node.image - self.node_type = canvas_node.node_type - self.name = canvas_node.name - self.canvas_node = canvas_node - self.node_configuration = node_config - self.p_top = node_config.top - - self.top = tk.Toplevel() - self.top.title(self.name + " image") - self.image_modification() - - def open_icon_dir(self, toplevel, entry_text): - filename = filedialog.askopenfilename( - initialdir=ICONS_DIR, - title="Open", - filetypes=( - ("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."), - ("All Files", "*"), - ), - ) - if len(filename) > 0: - img = Image.open(filename) - tk_img = ImageTk.PhotoImage(img) - lb = toplevel.grid_slaves(1, 0)[0] - lb.configure(image=tk_img) - lb.image = tk_img - entry_text.set(filename) - - def click_apply(self, toplevel, entry_text): - imgfile = entry_text.get() - if imgfile: - img = Image.open(imgfile) - tk_img = ImageTk.PhotoImage(img) - f = self.p_top.grid_slaves(row=0, column=0)[0] - lb = f.grid_slaves(row=0, column=3)[0] - lb.configure(image=tk_img) - lb.image = tk_img - self.image = tk_img - self.node_configuration.image = tk_img - toplevel.destroy() - - def image_modification(self): - f = tk.Frame(self.top) - entry_text = tk.StringVar() - image_file_label = tk.Label(f, text="Image file: ") - image_file_label.grid(row=0, column=0) - image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white") - image_file_entry.grid(row=0, column=1) - image_file_button = tk.Button( - f, text="...", command=lambda: self.open_icon_dir(self.top, entry_text) - ) - image_file_button.grid(row=0, column=2) - f.grid() - - img = tk.Label(self.top, image=self.image) - img.grid() - - f = tk.Frame(self.top) - apply_button = tk.Button( - f, text="Apply", command=lambda: self.click_apply(self.top, entry_text) - ) - apply_button.grid(row=0, column=0) - apply_to_multiple_button = tk.Button(f, text="Apply to multiple...") - apply_to_multiple_button.grid(row=0, column=1) - cancel_button = tk.Button(f, text="Cancel", command=self.top.destroy) - cancel_button.grid(row=0, column=2) - f.grid() diff --git a/coretk/coretk/images.py b/coretk/coretk/images.py index f9b5f870..768b33ba 100644 --- a/coretk/coretk/images.py +++ b/coretk/coretk/images.py @@ -10,6 +10,11 @@ from coretk.appdirs import LOCAL_ICONS_PATH class Images: images = {} + @classmethod + def create(cls, file_path): + image = Image.open(file_path) + return ImageTk.PhotoImage(image) + @classmethod def load_all(cls): for image in LOCAL_ICONS_PATH.glob("*"): @@ -17,8 +22,7 @@ class Images: @classmethod def load(cls, name, file_path): - image = Image.open(file_path) - tk_image = ImageTk.PhotoImage(image) + tk_image = cls.create(file_path) cls.images[name] = tk_image @classmethod diff --git a/coretk/coretk/menuaction.py b/coretk/coretk/menuaction.py index 64caf8ae..1d9adca1 100644 --- a/coretk/coretk/menuaction.py +++ b/coretk/coretk/menuaction.py @@ -11,8 +11,8 @@ from coretk.appdirs import XML_PATH from coretk.dialogs.hooks import HooksDialog from coretk.dialogs.sessionoptions import SessionOptionsDialog from coretk.dialogs.sessions import SessionsDialog -from coretk.setwallpaper import CanvasWallpaper -from coretk.sizeandscale import SizeAndScale +from coretk.dialogs.setwallpaper import CanvasWallpaper +from coretk.dialogs.sizeandscale import SizeAndScale def sub_menu_items(): diff --git a/coretk/coretk/nodeconfigtable.py b/coretk/coretk/nodeconfigtable.py deleted file mode 100644 index a1a7c1d2..00000000 --- a/coretk/coretk/nodeconfigtable.py +++ /dev/null @@ -1,164 +0,0 @@ -""" -Create toplevel for node configuration -""" -import logging -import os -import tkinter as tk -from tkinter import filedialog - -from PIL import Image, ImageTk - -from coretk.imagemodification import ImageModification -from coretk.nodeservice import NodeServices - -PATH = os.path.abspath(os.path.dirname(__file__)) -ICONS_DIR = os.path.join(PATH, "icons") - -NETWORKNODETYPES = ["switch", "hub", "wlan", "rj45", "tunnel"] -DEFAULTNODES = ["router", "host", "PC"] - - -class NodeConfig: - def __init__(self, canvas, canvas_node): - """ - create an instance of node configuration - - :param coretk.graph.CanvasGraph canvas: canvas object - :param coretk.graph.CanvasNode canvas_node: canvas node object - """ - self.canvas = canvas - self.image = canvas_node.image - self.node_type = canvas_node.node_type - self.name = canvas_node.name - self.canvas_node = canvas_node - - self.top = tk.Toplevel() - self.top.title(canvas_node.node_type + " configuration") - self.namevar = tk.StringVar(self.top, value="default name") - self.name_and_image_definition() - self.type_and_service_definition() - self.select_definition() - - def open_icon_dir(self, toplevel, entry_text): - filename = filedialog.askopenfilename( - initialdir=ICONS_DIR, - title="Open", - filetypes=( - ("images", "*.gif *.jpg *.png *.bmp *pcx *.tga ..."), - ("All Files", "*"), - ), - ) - if len(filename) > 0: - img = Image.open(filename) - tk_img = ImageTk.PhotoImage(img) - lb = toplevel.grid_slaves(1, 0)[0] - lb.configure(image=tk_img) - lb.image = tk_img - entry_text.set(filename) - - def click_apply(self, toplevel, entry_text): - imgfile = entry_text.get() - if imgfile: - img = Image.open(imgfile) - tk_img = ImageTk.PhotoImage(img) - lb = self.top.grid_slaves(row=0, column=3)[0] - lb.configure(image=tk_img) - lb.image = tk_img - self.image = tk_img - toplevel.destroy() - - def img_modification(self): - t = tk.Toplevel() - t.title(self.name + " image") - - f = tk.Frame(t) - entry_text = tk.StringVar() - image_file_label = tk.Label(f, text="Image file: ") - image_file_label.grid(row=0, column=0) - image_file_entry = tk.Entry(f, textvariable=entry_text, width=32, bg="white") - image_file_entry.grid(row=0, column=1) - image_file_button = tk.Button( - f, text="...", command=lambda: self.open_icon_dir(t, entry_text) - ) - image_file_button.grid(row=0, column=2) - f.grid() - - img = tk.Label(t, image=self.image) - img.grid() - - f = tk.Frame(t) - apply_button = tk.Button( - f, text="Apply", command=lambda: self.click_apply(t, entry_text) - ) - apply_button.grid(row=0, column=0) - apply_to_multiple_button = tk.Button(f, text="Apply to multiple...") - apply_to_multiple_button.grid(row=0, column=1) - cancel_button = tk.Button(f, text="Cancel", command=t.destroy) - cancel_button.grid(row=0, column=2) - f.grid() - - def name_and_image_definition(self): - f = tk.Frame(self.top, bg="#d9d9d9") - name_label = tk.Label(f, text="Node name: ", bg="#d9d9d9") - name_label.grid(padx=2, pady=2) - name_entry = tk.Entry(f, textvariable=self.namevar) - name_entry.grid(row=0, column=1, padx=2, pady=2) - - core_button = tk.Button(f, text="None") - core_button.grid(row=0, column=2, padx=2, pady=2) - img_button = tk.Button( - f, - image=self.image, - width=40, - height=40, - command=lambda: ImageModification(self.canvas, self.canvas_node, self), - bg="#d9d9d9", - ) - img_button.grid(row=0, column=3, padx=4, pady=4) - f.grid(padx=4, pady=4) - - def type_and_service_definition(self): - f = tk.Frame(self.top) - type_label = tk.Label(f, text="Type: ") - type_label.grid(row=0, column=0) - - type_button = tk.Button(f, text="None") - type_button.grid(row=0, column=1) - - service_button = tk.Button( - f, text="Services...", command=lambda: NodeServices() - ) - service_button.grid(row=0, column=2) - - f.grid(padx=2, pady=2) - - def config_apply(self): - """ - modify image of the canvas node - :return: nothing - """ - logging.debug("nodeconfigtable.py configuration apply") - self.canvas_node.image = self.image - self.canvas_node.canvas.itemconfig(self.canvas_node.id, image=self.image) - self.top.destroy() - - def config_cancel(self): - """ - save chosen image but not modify canvas node - :return: nothing - """ - logging.debug("nodeconfigtable.py configuration cancel") - self.canvas_node.image = self.image - self.top.destroy() - - def select_definition(self): - f = tk.Frame(self.top) - apply_button = tk.Button(f, text="Apply", command=self.config_apply) - apply_button.grid(row=0, column=0) - cancel_button = tk.Button(f, text="Cancel", command=self.config_cancel) - cancel_button.grid(row=0, column=1) - f.grid() - - def network_node_config(self): - self.name_and_image_definition() - self.select_definition()