Merge branch 'coretk' into coretk-servicefix

This commit is contained in:
Huy Pham 2019-12-09 08:54:53 -08:00
commit 11f771417e
9 changed files with 1896 additions and 255 deletions

View file

@ -5,12 +5,14 @@ import json
import logging
import os
import time
from pathlib import Path
from core.api.grpc import client, core_pb2
from coretk import appconfig
from coretk.dialogs.mobilityplayer import MobilityPlayer
from coretk.dialogs.sessions import SessionsDialog
from coretk.graph.shape import AnnotationData, Shape
from coretk.graph.shapeutils import ShapeType
from coretk.interface import InterfaceManager
from coretk.nodeutils import NodeDraw, NodeUtils
@ -27,7 +29,6 @@ LIFT_ORDER = [
"node",
]
OBSERVERS = {
"processes": "ps",
"ifconfig": "ifconfig",
@ -161,6 +162,8 @@ class CoreClient:
self.handle_node_event(event.node_event)
elif event.HasField("config_event"):
logging.info("config event: %s", event)
elif event.HasField("throughput_event"):
logging.info("throughput event: %s", event)
else:
logging.info("unhandled event: %s", event)
@ -295,35 +298,45 @@ class CoreClient:
def parse_metadata(self, config):
# canvas setting
canvas_config = config.get("canvas")
logging.info("canvas metadata: %s", canvas_config)
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)
for key, annotation_config in config.items():
if "annotation" in key:
annotation_config = json.loads(annotation_config)
config_type = annotation_config["type"]
if config_type in ["rectangle", "oval"]:
coords = tuple(annotation_config["iconcoords"])
if wallpaper:
wallpaper = str(appconfig.BACKGROUNDS_PATH.joinpath(wallpaper))
self.app.canvas.set_wallpaper(wallpaper)
# load saved shapes
shapes_config = config.get("shapes")
if shapes_config:
shapes_config = json.loads(shapes_config)
for shape_config in shapes_config:
logging.info("loading shape: %s", shape_config)
shape_type = shape_config["type"]
try:
shape_type = ShapeType(shape_type)
coords = shape_config["iconcoords"]
data = AnnotationData(
annotation_config["label"],
annotation_config["fontfamily"],
annotation_config["fontsize"],
annotation_config["labelcolor"],
annotation_config["color"],
annotation_config["border"],
annotation_config["width"],
shape_config["label"],
shape_config["fontfamily"],
shape_config["fontsize"],
shape_config["labelcolor"],
shape_config["color"],
shape_config["border"],
shape_config["width"],
shape_config["bold"],
shape_config["italic"],
shape_config["underline"],
)
shape = Shape(
self.app, self.app.canvas, None, None, coords, data, config_type
self.app, self.app.canvas, shape_type, *coords, data=data
)
self.app.canvas.shapes[shape.id] = shape
else:
logging.debug("not implemented")
except ValueError:
logging.exception("unknown shape: %s", shape_type)
for tag in LIFT_ORDER:
self.app.canvas.tag_raise(tag)
@ -421,6 +434,7 @@ class CoreClient:
service_configs,
file_configs,
)
self.set_metadata()
process_time = time.perf_counter() - start
logging.debug("start session(%s), result: %s", self.session_id, response.result)
self.app.statusbar.start_session_callback(process_time)
@ -441,6 +455,24 @@ class CoreClient:
self.app.statusbar.stop_session_callback(process_time)
logging.debug("stopped session(%s), result: %s", session_id, response.result)
def set_metadata(self):
# create canvas data
canvas_config = {
"wallpaper": Path(self.app.canvas.wallpaper_file).name,
"wallpaper-style": self.app.canvas.scale_option.get(),
}
canvas_config = json.dumps(canvas_config)
# create shapes data
shapes = []
for shape in self.app.canvas.shapes.values():
shapes.append(shape.metadata())
shapes = json.dumps(shapes)
metadata = {"canvas": canvas_config, "shapes": shapes}
response = self.client.set_session_metadata(self.session_id, metadata)
logging.info("set session metadata: %s", response)
def launch_terminal(self, node_id):
response = self.client.get_node_terminal(self.session_id, node_id)
logging.info("get terminal %s", response.terminal)

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@ import tkinter as tk
from tkinter import colorchooser, font, ttk
from coretk.dialogs.dialog import Dialog
from coretk.images import ImageEnum
from coretk.graph.shapeutils import is_draw_shape, is_shape_text
FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]
BORDER_WIDTH = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@ -13,40 +13,32 @@ BORDER_WIDTH = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
class ShapeDialog(Dialog):
def __init__(self, master, app, shape):
self.annotation_type = app.canvas.annotation_type
self.canvas = app.canvas
if self.is_shape():
super().__init__(master, app, "Add a new shape", modal=True)
self.id = shape.id
self.fill = None
self.border = None
if is_draw_shape(shape.shape_type):
title = "Add Shape"
else:
super().__init__(master, app, "Add a new text", modal=True)
title = "Add Text"
super().__init__(master, app, title, modal=True)
self.canvas = app.canvas
self.fill = None
self.border = None
self.shape = shape
data = shape.shape_data
self.shape_text = tk.StringVar(value=data.text)
self.font = tk.StringVar(value=data.font)
self.font_size = tk.IntVar(value=data.font_size)
self.text_color = data.text_color
self.fill_color = data.fill_color
fill_color = data.fill_color
if not fill_color:
fill_color = "#CFCFFF"
self.fill_color = fill_color
self.border_color = data.border_color
self.border_width = tk.IntVar(value=data.border_width)
self.bold = tk.IntVar(value=data.bold)
self.italic = tk.IntVar(value=data.italic)
self.underline = tk.IntVar(value=data.underline)
self.border_width = tk.IntVar(value=0)
self.bold = tk.BooleanVar(value=data.bold)
self.italic = tk.BooleanVar(value=data.italic)
self.underline = tk.BooleanVar(value=data.underline)
self.top.columnconfigure(0, weight=1)
self.draw()
def is_shape(self):
return (
self.annotation_type == ImageEnum.OVAL
or self.annotation_type == ImageEnum.RECTANGLE
)
def is_text(self):
return self.annotation_type == ImageEnum.TEXT
def draw(self):
frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1)
@ -85,7 +77,7 @@ class ShapeDialog(Dialog):
button.grid(row=0, column=2)
frame.grid(row=2, column=0, sticky="nsew", padx=3, pady=3)
if self.is_shape():
if is_draw_shape(self.shape.shape_type):
frame = ttk.Frame(self.top)
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
@ -152,15 +144,14 @@ class ShapeDialog(Dialog):
self.border.config(background=color[1], text=color[1])
def cancel(self):
if self.is_shape() and not self.canvas.shapes[self.id].created:
self.canvas.delete(self.id)
self.canvas.shapes.pop(self.id)
self.shape.delete()
self.canvas.shapes.pop(self.shape.id)
self.destroy()
def click_add(self):
if self.is_shape():
if is_draw_shape(self.shape.shape_type):
self.add_shape()
elif self.is_text():
elif is_shape_text(self.shape.shape_type):
self.add_text()
self.destroy()
@ -171,11 +162,11 @@ class ShapeDialog(Dialog):
"""
size = int(self.font_size.get())
text_font = [self.font.get(), size]
if self.bold.get() == 1:
if self.bold.get():
text_font.append("bold")
if self.italic.get() == 1:
if self.italic.get():
text_font.append("italic")
if self.underline.get() == 1:
if self.underline.get():
text_font.append("underline")
return text_font
@ -212,29 +203,15 @@ class ShapeDialog(Dialog):
:return: nothing
"""
text = self.shape_text.get()
x = self.shape.x0
y = self.shape.y0
text_font = self.make_font()
if self.shape.text_id is None:
tid = self.canvas.create_text(
x, y, text=text, fill=self.text_color, font=text_font, tags="text"
)
self.shape.text_id = tid
self.id = tid
self.shape.id = tid
self.canvas.texts[tid] = self.shape
self.shape.created = True
self.canvas.itemconfig(
self.shape.id, text=text, fill=self.text_color, font=text_font
)
self.save_text()
print(self.canvas.texts)
# self.canvas.shapes[self.id].created = True
# else:
# self.canvas.itemconfig(
# self.shape.text_id, text=text, fill=self.text_color, font=f
# )
def add_shape(self):
self.canvas.itemconfig(
self.id,
self.shape.id,
fill=self.fill_color,
dash="",
outline=self.border_color,
@ -242,7 +219,7 @@ class ShapeDialog(Dialog):
)
shape_text = self.shape_text.get()
size = int(self.font_size.get())
x0, y0, x1, y1 = self.canvas.bbox(self.id)
x0, y0, x1, y1 = self.canvas.bbox(self.shape.id)
_y = y0 + 1.5 * size
_x = (x0 + x1) / 2
text_font = self.make_font()

View file

@ -16,8 +16,3 @@ class ScaleOption(enum.Enum):
CENTERED = 2
SCALED = 3
TILED = 4
class ShapeType(enum.Enum):
OVAL = 0
RECTANGLE = 1

View file

@ -10,7 +10,8 @@ from coretk.graph.enums import GraphMode, ScaleOption
from coretk.graph.linkinfo import LinkInfo, Throughput
from coretk.graph.node import CanvasNode
from coretk.graph.shape import Shape
from coretk.images import ImageEnum, Images
from coretk.graph.shapeutils import is_draw_shape
from coretk.images import Images
from coretk.nodeutils import NodeUtils
ABOVE_WALLPAPER = ["edge", "linkinfo", "wireless", "antenna", "nodename", "node"]
@ -44,7 +45,6 @@ class CanvasGraph(tk.Canvas):
self.nodes = {}
self.edges = {}
self.shapes = {}
self.texts = {}
self.wireless_edges = {}
self.drawing_edge = None
self.grid = None
@ -244,14 +244,12 @@ class CanvasGraph(tk.Canvas):
self.context = None
else:
if self.mode == GraphMode.ANNOTATION:
if self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]:
self.focus_set()
x, y = self.canvas_xy(event)
if self.shape_drawing:
self.shapes[self.selected].shape_complete(x, y)
self.shape_drawing = False
elif self.annotation_type == ImageEnum.TEXT:
self.text.shape_complete(self.text.cursor_x, self.text.cursor_y)
self.focus_set()
x, y = self.canvas_xy(event)
if self.shape_drawing:
shape = self.shapes[self.selected]
shape.shape_complete(x, y)
self.shape_drawing = False
else:
self.focus_set()
self.selected = self.get_selected(event)
@ -403,15 +401,11 @@ class CanvasGraph(tk.Canvas):
self.drawing_edge = CanvasEdge(x, y, x, y, selected, self)
if self.mode == GraphMode.ANNOTATION and selected is None:
if self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]:
x, y = self.canvas_xy(event)
shape = Shape(self.app, self, x, y)
self.selected = shape.id
self.shapes[shape.id] = shape
self.shape_drawing = True
elif self.annotation_type == ImageEnum.TEXT:
x, y = self.canvas_xy(event)
self.text = Shape(self.app, self, x, y)
x, y = self.canvas_xy(event)
shape = Shape(self.app, self, self.annotation_type, x, y)
self.selected = shape.id
self.shape_drawing = True
self.shapes[shape.id] = shape
if self.mode == GraphMode.SELECT:
if selected is not None:
@ -448,12 +442,10 @@ class CanvasGraph(tk.Canvas):
x1, y1, _, _ = self.coords(self.drawing_edge.id)
self.coords(self.drawing_edge.id, x1, y1, x2, y2)
if self.mode == GraphMode.ANNOTATION:
if (
self.annotation_type in [ImageEnum.OVAL, ImageEnum.RECTANGLE]
and self.shape_drawing
):
if is_draw_shape(self.annotation_type) and self.shape_drawing:
x, y = self.canvas_xy(event)
self.shapes[self.selected].shape_motion(x, y)
shape = self.shapes[self.selected]
shape.shape_motion(x, y)
if (
self.mode == GraphMode.SELECT
and self.selected is not None

View file

@ -1,8 +1,7 @@
"""
class for shapes
"""
import logging
from coretk.dialogs.shapemod import ShapeDialog
from coretk.images import ImageEnum
from coretk.graph.shapeutils import ShapeType
ABOVE_COMPONENT = ["gridline", "edge", "linkinfo", "antenna", "node", "nodename"]
@ -14,14 +13,13 @@ class AnnotationData:
font="Arial",
font_size=12,
text_color="#000000",
fill_color="#CFCFFF",
fill_color="",
border_color="#000000",
border_width=0,
bold=0,
italic=0,
underline=0,
border_width=1,
bold=False,
italic=False,
underline=False,
):
self.text = text
self.font = font
self.font_size = font_size
@ -35,72 +33,103 @@ class AnnotationData:
class Shape:
def __init__(
self,
app,
canvas,
top_x=None,
top_y=None,
coords=None,
data=None,
shape_type=None,
):
def __init__(self, app, canvas, shape_type, x1, y1, x2=None, y2=None, data=None):
self.app = app
self.canvas = canvas
self.shape_type = shape_type
self.id = None
self.text_id = None
self.x1 = x1
self.y1 = y1
if x2 is None:
x2 = x1
self.x2 = x2
if y2 is None:
y2 = y1
self.y2 = y2
if data is None:
self.x0 = top_x
self.y0 = top_y
self.created = False
self.text_id = None
self.shape_data = AnnotationData()
canvas.delete(canvas.find_withtag("selectednodes"))
annotation_type = self.canvas.annotation_type
if annotation_type == ImageEnum.OVAL:
self.id = canvas.create_oval(
top_x, top_y, top_x, top_y, tags="shape", dash="-"
)
elif annotation_type == ImageEnum.RECTANGLE:
self.id = canvas.create_rectangle(
top_x, top_y, top_x, top_y, tags="shape", dash="-"
)
self.cursor_x = x1
self.cursor_y = y1
else:
x0, y0, x1, y1 = coords
self.x0 = x0
self.y0 = y0
self.created = True
if shape_type == "oval":
self.id = self.canvas.create_oval(
x0,
y0,
x1,
y1,
tags="shape",
fill=data.fill_color,
outline=data.border_color,
width=data.border_width,
)
elif shape_type == "rectangle":
self.id = self.canvas.create_rectangle(
x0,
y0,
x1,
y1,
tags="shape",
fill=data.fill_color,
outline=data.border_color,
width=data.border_width,
)
_x = (x0 + x1) / 2
_y = y0 + 1.5 * data.font_size
self.text_id = self.canvas.create_text(
_x, _y, tags="shapetext", text=data.text, fill=data.text_color
)
self.shape_data = data
self.cursor_x = None
self.cursor_y = None
self.cursor_x = None
self.cursor_y = None
self.draw()
def draw(self):
if self.created:
dash = None
else:
dash = "-"
if self.shape_type == ShapeType.OVAL:
self.id = self.canvas.create_oval(
self.x1,
self.y1,
self.x2,
self.y2,
tags="shape",
dash=dash,
fill=self.shape_data.fill_color,
outline=self.shape_data.border_color,
width=self.shape_data.border_width,
)
self.draw_shape_text()
elif self.shape_type == ShapeType.RECTANGLE:
self.id = self.canvas.create_rectangle(
self.x1,
self.y1,
self.x2,
self.y2,
tags="shape",
dash=dash,
fill=self.shape_data.fill_color,
outline=self.shape_data.border_color,
width=self.shape_data.border_width,
)
self.draw_shape_text()
elif self.shape_type == ShapeType.TEXT:
font = self.get_font()
self.id = self.canvas.create_text(
self.x1,
self.y1,
tags="shapetext",
text=self.shape_data.text,
fill=self.shape_data.text_color,
font=font,
)
else:
logging.error("unknown shape type: %s", self.shape_type)
self.created = True
def get_font(self):
font = [self.shape_data.font, self.shape_data.font_size]
if self.shape_data.bold:
font.append("bold")
if self.shape_data.italic:
font.append("italic")
if self.shape_data.underline:
font.append("underline")
return font
def draw_shape_text(self):
if self.shape_data.text:
x = (self.x1 + self.x2) / 2
y = self.y1 + 1.5 * self.shape_data.font_size
font = self.get_font()
self.text_id = self.canvas.create_text(
x,
y,
tags="shapetext",
text=self.shape_data.text,
fill=self.shape_data.text_color,
font=font,
)
def shape_motion(self, x1, y1):
self.canvas.coords(self.id, self.x0, self.y0, x1, y1)
self.canvas.coords(self.id, self.x1, self.y1, x1, y1)
def shape_complete(self, x, y):
for component in ABOVE_COMPONENT:
@ -122,3 +151,20 @@ class Shape:
def delete(self):
self.canvas.delete(self.id)
self.canvas.delete(self.text_id)
def metadata(self):
coords = self.canvas.coords(self.id)
return {
"type": self.shape_type.value,
"iconcoords": coords,
"label": self.shape_data.text,
"fontfamily": self.shape_data.font,
"fontsize": self.shape_data.font_size,
"labelcolor": self.shape_data.text_color,
"color": self.shape_data.fill_color,
"border": self.shape_data.border_color,
"width": self.shape_data.border_width,
"bold": self.shape_data.bold,
"italic": self.shape_data.italic,
"underline": self.shape_data.underline,
}

View file

@ -0,0 +1,19 @@
import enum
class ShapeType(enum.Enum):
MARKER = "marker"
OVAL = "oval"
RECTANGLE = "rectangle"
TEXT = "text"
SHAPES = {ShapeType.OVAL, ShapeType.RECTANGLE}
def is_draw_shape(shape_type):
return shape_type in SHAPES
def is_shape_text(shape_type):
return shape_type == ShapeType.TEXT

View file

@ -6,6 +6,7 @@ from tkinter import ttk
from coretk.dialogs.customnodes import CustomNodesDialog
from coretk.graph.enums import GraphMode
from coretk.graph.shapeutils import ShapeType
from coretk.images import ImageEnum, Images
from coretk.nodeutils import NodeUtils
from coretk.tooltip import Tooltip
@ -291,18 +292,18 @@ class Toolbar(ttk.Frame):
self.hide_pickers()
self.annotation_picker = ttk.Frame(self.master)
nodes = [
(ImageEnum.MARKER, "marker"),
(ImageEnum.OVAL, "oval"),
(ImageEnum.RECTANGLE, "rectangle"),
(ImageEnum.TEXT, "text"),
(ImageEnum.MARKER, ShapeType.MARKER),
(ImageEnum.OVAL, ShapeType.OVAL),
(ImageEnum.RECTANGLE, ShapeType.RECTANGLE),
(ImageEnum.TEXT, ShapeType.TEXT),
]
for image_enum, tooltip in nodes:
for image_enum, shape_type in nodes:
image = icon(image_enum)
self.create_picker_button(
image,
partial(self.update_annotation, image, image_enum),
partial(self.update_annotation, image, shape_type),
self.annotation_picker,
tooltip,
shape_type.value,
)
self.design_select(self.annotation_button)
self.annotation_button.after(
@ -362,13 +363,13 @@ class Toolbar(ttk.Frame):
self.design_frame.tkraise()
def update_annotation(self, image, image_enum):
def update_annotation(self, image, shape_type):
logging.info("clicked annotation: ")
self.hide_pickers()
self.annotation_button.configure(image=image)
self.annotation_button.image = image
self.app.canvas.mode = GraphMode.ANNOTATION
self.app.canvas.annotation_type = image_enum
self.app.canvas.annotation_type = shape_type
def click_run_button(self):
logging.debug("Click on RUN button")

View file

@ -117,8 +117,14 @@ class NodeElement:
def add_position(self):
x = self.node.position.x
if x is not None:
x = int(x)
y = self.node.position.y
if y is not None:
y = int(y)
z = self.node.position.z
if z is not None:
z = int(z)
lat, lon, alt = None, None, None
if x is not None and y is not None:
lat, lon, alt = self.session.location.getgeo(x, y, z)