From 5a387537bb9f57d99b211379509694bdf8da4e90 Mon Sep 17 00:00:00 2001
From: Blake Harnden <32446120+bharnden@users.noreply.github.com>
Date: Wed, 4 Dec 2019 13:40:35 -0800
Subject: [PATCH] updates clean up setting wallpaper for graph canvas, updates
to read metadata for canvas to display wallpaper from loaded xml file, update
to allow reopening mobility player from node context
---
coretk/coretk/coreclient.py | 37 ++++++++++++++-----
coretk/coretk/data/xmls/sample1.xml | 2 +-
coretk/coretk/dialogs/canvasbackground.py | 23 +++---------
coretk/coretk/dialogs/mobilityplayer.py | 44 ++++++++++++++++++++---
coretk/coretk/graph.py | 24 +++++++++++--
5 files changed, 94 insertions(+), 36 deletions(-)
diff --git a/coretk/coretk/coreclient.py b/coretk/coretk/coreclient.py
index fec00a73..ef617ac0 100644
--- a/coretk/coretk/coreclient.py
+++ b/coretk/coretk/coreclient.py
@@ -1,12 +1,14 @@
"""
Incorporate grpc into python tkinter GUI
"""
+import json
import logging
import os
import time
from core.api.grpc import client, core_pb2
-from coretk.dialogs.mobilityplayer import MobilityPlayerDialog
+from coretk import appconfig
+from coretk.dialogs.mobilityplayer import MobilityPlayer
from coretk.dialogs.sessions import SessionsDialog
from coretk.interface import InterfaceManager
from coretk.nodeutils import NodeDraw, NodeUtils
@@ -141,6 +143,8 @@ class CoreClient:
logging.warning("unknown session event: %s", session_event)
elif event.HasField("node_event"):
self.handle_node_event(event.node_event)
+ elif event.HasField("config_event"):
+ logging.info("config event: %s", event)
else:
logging.info("unhandled event: %s", event)
@@ -164,7 +168,7 @@ class CoreClient:
x = event.node.position.x
y = event.node.position.y
canvas_node = self.canvas_nodes[node_id]
- canvas_node.move(x, y)
+ canvas_node.move(x, y, update=False)
def handle_throughputs(self, event):
interface_throughputs = event.interface_throughputs
@@ -189,7 +193,6 @@ class CoreClient:
# 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.state = session.state
self.client.events(self.session_id, self.handle_events)
@@ -235,9 +238,6 @@ class CoreClient:
node_id = int(_id / 1000)
self.set_emane_model_config(node_id, config.model, config.config, interface)
- # draw session
- self.app.canvas.reset_and_redraw(session)
-
# get node service config and file config
for node in session.nodes:
self.created_nodes.add(node.id)
@@ -262,6 +262,13 @@ class CoreClient:
self.file_configs[node.id][service] = {}
self.file_configs[node.id][service][file] = response.data
+ # draw session
+ self.app.canvas.reset_and_redraw(session)
+
+ # get metadata
+ response = self.client.get_session_metadata(self.session_id)
+ self.parse_metadata(response.config)
+
if self.is_runtime():
self.app.toolbar.runtime_frame.tkraise()
else:
@@ -271,6 +278,18 @@ class CoreClient:
def is_runtime(self):
return self.state == core_pb2.SessionState.RUNTIME
+ def parse_metadata(self, config):
+ # canvas settings
+ canvas_config = config.get("canvas")
+ if canvas_config:
+ logging.info("canvas metadata: %s", canvas_config)
+ canvas_config = json.loads(canvas_config)
+ wallpaper_style = canvas_config["wallpaper-style"]
+ self.app.canvas.scale_option.set(wallpaper_style)
+ wallpaper = canvas_config["wallpaper"]
+ wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
+ self.app.canvas.set_wallpaper(wallpaper)
+
def create_new_session(self):
"""
Create a new session
@@ -372,9 +391,9 @@ class CoreClient:
# display mobility players
for node_id, config in self.mobility_configs.items():
canvas_node = self.canvas_nodes[node_id]
- dialog = MobilityPlayerDialog(self.app, self.app, canvas_node, config)
- dialog.show()
- self.mobility_players[node_id] = dialog
+ mobility_player = MobilityPlayer(self.app, self.app, canvas_node, config)
+ mobility_player.show()
+ self.mobility_players[node_id] = mobility_player
def stop_session(self, session_id=None):
if not session_id:
diff --git a/coretk/coretk/data/xmls/sample1.xml b/coretk/coretk/data/xmls/sample1.xml
index 8bda5b8c..7c8ccf72 100644
--- a/coretk/coretk/data/xmls/sample1.xml
+++ b/coretk/coretk/data/xmls/sample1.xml
@@ -269,7 +269,7 @@ router ospf6
-
+
diff --git a/coretk/coretk/dialogs/canvasbackground.py b/coretk/coretk/dialogs/canvasbackground.py
index 84b0bdb6..844b5595 100644
--- a/coretk/coretk/dialogs/canvasbackground.py
+++ b/coretk/coretk/dialogs/canvasbackground.py
@@ -5,14 +5,11 @@ import logging
import tkinter as tk
from tkinter import filedialog, ttk
-from PIL import Image
-
from coretk.appconfig import BACKGROUNDS_PATH
from coretk.dialogs.dialog import Dialog
from coretk.images import Images
PADX = 5
-ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
class CanvasBackgroundDialog(Dialog):
@@ -178,23 +175,11 @@ class CanvasBackgroundDialog(Dialog):
filename = self.filename.get()
if not filename:
- self.canvas.delete(self.canvas.wallpaper_id)
- self.canvas.wallpaper = None
- self.canvas.wallpaper_file = None
- self.destroy()
- return
- try:
- img = Image.open(filename)
- self.canvas.wallpaper = img
- self.canvas.wallpaper_file = filename
- self.canvas.redraw()
- for component in ABOVE_WALLPAPER:
- self.canvas.tag_raise(component)
+ filename = None
+ try:
+ self.canvas.set_wallpaper(filename)
except FileNotFoundError:
logging.error("invalid background: %s", filename)
- if self.canvas.wallpaper_id:
- self.canvas.delete(self.canvas.wallpaper_id)
- self.canvas.wallpaper_id = None
- self.canvas.wallpaper_file = None
+
self.destroy()
diff --git a/coretk/coretk/dialogs/mobilityplayer.py b/coretk/coretk/dialogs/mobilityplayer.py
index 65b16058..136e6179 100644
--- a/coretk/coretk/dialogs/mobilityplayer.py
+++ b/coretk/coretk/dialogs/mobilityplayer.py
@@ -1,7 +1,7 @@
import tkinter as tk
from tkinter import ttk
-from core.api.grpc import core_pb2
+from core.api.grpc.core_pb2 import MobilityAction
from coretk.dialogs.dialog import Dialog
from coretk.images import ImageEnum, Images
@@ -9,6 +9,42 @@ PAD = 5
ICON_SIZE = 16
+class MobilityPlayer:
+ def __init__(self, master, app, canvas_node, config):
+ self.master = master
+ self.app = app
+ self.canvas_node = canvas_node
+ self.config = config
+ self.dialog = None
+ self.state = None
+
+ def show(self):
+ if self.dialog:
+ self.dialog.destroy()
+ self.dialog = MobilityPlayerDialog(
+ self.master, self.app, self.canvas_node, self.config
+ )
+ if self.state == MobilityAction.START:
+ self.set_play()
+ elif self.state == MobilityAction.PAUSE:
+ self.set_pause()
+ else:
+ self.set_stop()
+ self.dialog.show()
+
+ def set_play(self):
+ self.dialog.set_play()
+ self.state = MobilityAction.START
+
+ def set_pause(self):
+ self.dialog.set_pause()
+ self.state = MobilityAction.PAUSE
+
+ def set_stop(self):
+ self.dialog.set_stop()
+ self.state = MobilityAction.STOP
+
+
class MobilityPlayerDialog(Dialog):
def __init__(self, master, app, canvas_node, config):
super().__init__(
@@ -88,19 +124,19 @@ class MobilityPlayerDialog(Dialog):
self.set_play()
session_id = self.app.core.session_id
self.app.core.client.mobility_action(
- session_id, self.node.id, core_pb2.MobilityAction.START
+ session_id, self.node.id, MobilityAction.START
)
def click_pause(self):
self.set_pause()
session_id = self.app.core.session_id
self.app.core.client.mobility_action(
- session_id, self.node.id, core_pb2.MobilityAction.PAUSE
+ session_id, self.node.id, MobilityAction.PAUSE
)
def click_stop(self):
self.set_stop()
session_id = self.app.core.session_id
self.app.core.client.mobility_action(
- session_id, self.node.id, core_pb2.MobilityAction.STOP
+ session_id, self.node.id, MobilityAction.STOP
)
diff --git a/coretk/coretk/graph.py b/coretk/coretk/graph.py
index 7389be52..7ef341a3 100644
--- a/coretk/coretk/graph.py
+++ b/coretk/coretk/graph.py
@@ -3,7 +3,7 @@ import logging
import tkinter as tk
from tkinter import font
-from PIL import ImageTk
+from PIL import Image, ImageTk
from core.api.grpc import core_pb2
from core.api.grpc.core_pb2 import NodeType
@@ -21,6 +21,7 @@ from coretk.nodeutils import NodeUtils
from coretk.shape import Shape
NODE_TEXT_OFFSET = 5
+ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
class GraphMode(enum.Enum):
@@ -583,6 +584,21 @@ class CanvasGraph(tk.Canvas):
else:
self.itemconfig("gridline", state=tk.HIDDEN)
+ def set_wallpaper(self, filename):
+ logging.info("setting wallpaper: %s", filename)
+ if filename is not None:
+ img = Image.open(filename)
+ self.wallpaper = img
+ self.wallpaper_file = filename
+ self.redraw()
+ for component in ABOVE_WALLPAPER:
+ self.tag_raise(component)
+ else:
+ if self.wallpaper_id is not None:
+ self.delete(self.wallpaper_id)
+ self.wallpaper = None
+ self.wallpaper_file = None
+
def is_selection_mode(self):
return self.mode == GraphMode.SELECT
@@ -696,7 +712,7 @@ class CanvasNode:
self.canvas.itemconfig(self.id, image=self.image)
self.canvas.itemconfig(self.text_id, text=self.core_node.name)
- def move(self, x, y):
+ def move(self, x, y, update=True):
old_x = self.core_node.position.x
old_y = self.core_node.position.y
x_offset = x - old_x
@@ -720,7 +736,7 @@ class CanvasNode:
self.canvas.coords(edge.id, x, y, x2, y2)
else:
self.canvas.coords(edge.id, x1, y1, x, y)
- if self.app.core.is_runtime():
+ if self.app.core.is_runtime() and update:
self.app.core.edit_node(self.core_node.id, int(x), int(y))
def on_enter(self, event):
@@ -784,6 +800,8 @@ class CanvasNode:
def show_mobility_player(self):
self.canvas.context = None
+ mobility_player = self.app.core.mobility_players[self.core_node.id]
+ mobility_player.show()
def show_emane_config(self):
self.canvas.context = None