fix merge conflict
This commit is contained in:
commit
22e773df1b
13 changed files with 396 additions and 281 deletions
|
@ -40,7 +40,7 @@ class Application(tk.Frame):
|
||||||
def setup_app(self):
|
def setup_app(self):
|
||||||
self.master.title("CORE")
|
self.master.title("CORE")
|
||||||
self.master.geometry("1000x800")
|
self.master.geometry("1000x800")
|
||||||
image = Images.get(ImageEnum.CORE.value)
|
image = Images.get(ImageEnum.CORE)
|
||||||
self.master.tk.call("wm", "iconphoto", self.master._w, image)
|
self.master.tk.call("wm", "iconphoto", self.master._w, image)
|
||||||
self.pack(fill=tk.BOTH, expand=True)
|
self.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
|
95
coretk/coretk/configutils.py
Normal file
95
coretk/coretk/configutils.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
import enum
|
||||||
|
import logging
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigType(enum.Enum):
|
||||||
|
STRING = 10
|
||||||
|
BOOL = 11
|
||||||
|
|
||||||
|
|
||||||
|
def create_config(master, config, padx=2, pady=2):
|
||||||
|
"""
|
||||||
|
Creates a scrollable canvas with an embedded window for displaying configuration
|
||||||
|
options. Will use grid layout to consume row 0 and columns 0-2.
|
||||||
|
|
||||||
|
:param master: master to add scrollable canvas to
|
||||||
|
:param dict config: config option mapping keys to config options
|
||||||
|
:param int padx: x padding for widgets
|
||||||
|
:param int pady: y padding for widgets
|
||||||
|
:return: widget value mapping
|
||||||
|
"""
|
||||||
|
master.rowconfigure(0, weight=1)
|
||||||
|
master.columnconfigure(0, weight=1)
|
||||||
|
master.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
|
canvas = tk.Canvas(master, highlightthickness=0)
|
||||||
|
canvas.grid(row=0, columnspan=2, sticky="nsew", padx=padx, pady=pady)
|
||||||
|
canvas.columnconfigure(0, weight=1)
|
||||||
|
canvas.rowconfigure(0, weight=1)
|
||||||
|
|
||||||
|
scroll_y = tk.Scrollbar(master, orient="vertical", command=canvas.yview)
|
||||||
|
scroll_y.grid(row=0, column=2, sticky="ns")
|
||||||
|
|
||||||
|
frame = tk.Frame(canvas, padx=padx, pady=pady)
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=3)
|
||||||
|
|
||||||
|
values = {}
|
||||||
|
for index, key in enumerate(sorted(config)):
|
||||||
|
option = config[key]
|
||||||
|
label = tk.Label(frame, text=option.label)
|
||||||
|
label.grid(row=index, pady=pady, padx=padx, sticky="ew")
|
||||||
|
value = tk.StringVar()
|
||||||
|
config_type = ConfigType(option.type)
|
||||||
|
if config_type == ConfigType.BOOL:
|
||||||
|
select = tuple(option.select)
|
||||||
|
combobox = ttk.Combobox(frame, textvariable=value, values=select)
|
||||||
|
combobox.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||||
|
if option.value == "1":
|
||||||
|
value.set("On")
|
||||||
|
else:
|
||||||
|
value.set("Off")
|
||||||
|
elif config_type == ConfigType.STRING:
|
||||||
|
entry = tk.Entry(frame, textvariable=value)
|
||||||
|
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||||
|
else:
|
||||||
|
logging.error("unhandled config option type: %s", config_type)
|
||||||
|
values[key] = value
|
||||||
|
|
||||||
|
frame_id = canvas.create_window(0, 0, anchor="nw", window=frame)
|
||||||
|
canvas.update_idletasks()
|
||||||
|
canvas.configure(scrollregion=canvas.bbox("all"), yscrollcommand=scroll_y.set)
|
||||||
|
|
||||||
|
frame.bind(
|
||||||
|
"<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all"))
|
||||||
|
)
|
||||||
|
canvas.bind(
|
||||||
|
"<Configure>", lambda event: canvas.itemconfig(frame_id, width=event.width)
|
||||||
|
)
|
||||||
|
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
def parse_config(options, values):
|
||||||
|
"""
|
||||||
|
Given a set of configurations, parse out values and transform them when needed.
|
||||||
|
|
||||||
|
:param dict options: option key mapping to configuration options
|
||||||
|
:param dict values: option key mapping to widget values
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
config = {}
|
||||||
|
for key in options:
|
||||||
|
option = options[key]
|
||||||
|
value = values[key]
|
||||||
|
config_type = ConfigType(option.type)
|
||||||
|
config_value = value.get()
|
||||||
|
if config_type == ConfigType.BOOL:
|
||||||
|
if config_value == "On":
|
||||||
|
config_value = "1"
|
||||||
|
else:
|
||||||
|
config_value = "0"
|
||||||
|
config[key] = config_value
|
||||||
|
return config
|
|
@ -6,8 +6,8 @@ import os
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from core.api.grpc import client, core_pb2
|
from core.api.grpc import client, core_pb2
|
||||||
|
from coretk.dialogs.sessions import SessionsDialog
|
||||||
from coretk.linkinfo import Throughput
|
from coretk.linkinfo import Throughput
|
||||||
from coretk.querysessiondrawing import SessionTable
|
|
||||||
from coretk.wirelessconnection import WirelessConnection
|
from coretk.wirelessconnection import WirelessConnection
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,12 +18,9 @@ class CoreGrpc:
|
||||||
"""
|
"""
|
||||||
self.core = client.CoreGrpcClient()
|
self.core = client.CoreGrpcClient()
|
||||||
self.session_id = sid
|
self.session_id = sid
|
||||||
|
|
||||||
self.node_ids = []
|
self.node_ids = []
|
||||||
|
self.app = app
|
||||||
self.master = app.master
|
self.master = app.master
|
||||||
|
|
||||||
# self.set_up()
|
|
||||||
self.interface_helper = None
|
self.interface_helper = None
|
||||||
self.throughput_draw = Throughput(app.canvas, self)
|
self.throughput_draw = Throughput(app.canvas, self)
|
||||||
self.wireless_draw = WirelessConnection(app.canvas, self)
|
self.wireless_draw = WirelessConnection(app.canvas, self)
|
||||||
|
@ -64,16 +61,6 @@ class CoreGrpc:
|
||||||
self.core.events(self.session_id, self.log_event)
|
self.core.events(self.session_id, self.log_event)
|
||||||
# self.core.throughputs(self.log_throughput)
|
# self.core.throughputs(self.log_throughput)
|
||||||
|
|
||||||
def query_existing_sessions(self, sessions):
|
|
||||||
"""
|
|
||||||
Query for existing sessions and prompt to join one
|
|
||||||
|
|
||||||
:param repeated core_pb2.SessionSummary sessions: summaries of all the existing sessions
|
|
||||||
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
SessionTable(self, self.master)
|
|
||||||
|
|
||||||
def delete_session(self, custom_sid=None):
|
def delete_session(self, custom_sid=None):
|
||||||
if custom_sid is None:
|
if custom_sid is None:
|
||||||
sid = self.session_id
|
sid = self.session_id
|
||||||
|
@ -102,18 +89,15 @@ class CoreGrpc:
|
||||||
:return: existing sessions
|
:return: existing sessions
|
||||||
"""
|
"""
|
||||||
self.core.connect()
|
self.core.connect()
|
||||||
|
|
||||||
response = self.core.get_sessions()
|
response = self.core.get_sessions()
|
||||||
# logging.info("coregrpc.py: all sessions: %s", response)
|
|
||||||
|
|
||||||
# if there are no sessions, create a new session, else join a session
|
# if there are no sessions, create a new session, else join a session
|
||||||
sessions = response.sessions
|
sessions = response.sessions
|
||||||
|
|
||||||
if len(sessions) == 0:
|
if len(sessions) == 0:
|
||||||
self.create_new_session()
|
self.create_new_session()
|
||||||
else:
|
else:
|
||||||
|
dialog = SessionsDialog(self.app, self.app)
|
||||||
self.query_existing_sessions(sessions)
|
dialog.show()
|
||||||
|
|
||||||
def get_session_state(self):
|
def get_session_state(self):
|
||||||
response = self.core.get_session(self.session_id)
|
response = self.core.get_session(self.session_id)
|
||||||
|
|
|
@ -594,7 +594,7 @@ class CoreMenubar(object):
|
||||||
|
|
||||||
session_menu.add_command(
|
session_menu.add_command(
|
||||||
label="Change sessions...",
|
label="Change sessions...",
|
||||||
command=action.session_change_sessions,
|
command=self.menu_action.session_change_sessions,
|
||||||
underline=0,
|
underline=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ class CoreMenubar(object):
|
||||||
underline=0,
|
underline=0,
|
||||||
)
|
)
|
||||||
session_menu.add_command(
|
session_menu.add_command(
|
||||||
label="Options...", command=action.session_options, underline=0
|
label="Options...", command=self.menu_action.session_options, underline=0
|
||||||
)
|
)
|
||||||
|
|
||||||
self.menubar.add_cascade(label="Session", menu=session_menu, underline=0)
|
self.menubar.add_cascade(label="Session", menu=session_menu, underline=0)
|
||||||
|
|
|
@ -200,55 +200,55 @@ class CoreToolbar(object):
|
||||||
def pick_router(self, main_button):
|
def pick_router(self, main_button):
|
||||||
logging.debug("Pick router option")
|
logging.debug("Pick router option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.ROUTER.value))
|
main_button.configure(image=Images.get(ImageEnum.ROUTER))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.ROUTER.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.ROUTER)
|
||||||
self.canvas.draw_node_name = "router"
|
self.canvas.draw_node_name = "router"
|
||||||
|
|
||||||
def pick_host(self, main_button):
|
def pick_host(self, main_button):
|
||||||
logging.debug("Pick host option")
|
logging.debug("Pick host option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.HOST.value))
|
main_button.configure(image=Images.get(ImageEnum.HOST))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.HOST.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.HOST)
|
||||||
self.canvas.draw_node_name = "host"
|
self.canvas.draw_node_name = "host"
|
||||||
|
|
||||||
def pick_pc(self, main_button):
|
def pick_pc(self, main_button):
|
||||||
logging.debug("Pick PC option")
|
logging.debug("Pick PC option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.PC.value))
|
main_button.configure(image=Images.get(ImageEnum.PC))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.PC.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.PC)
|
||||||
self.canvas.draw_node_name = "PC"
|
self.canvas.draw_node_name = "PC"
|
||||||
|
|
||||||
def pick_mdr(self, main_button):
|
def pick_mdr(self, main_button):
|
||||||
logging.debug("Pick MDR option")
|
logging.debug("Pick MDR option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.MDR.value))
|
main_button.configure(image=Images.get(ImageEnum.MDR))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.MDR.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.MDR)
|
||||||
self.canvas.draw_node_name = "mdr"
|
self.canvas.draw_node_name = "mdr"
|
||||||
|
|
||||||
def pick_prouter(self, main_button):
|
def pick_prouter(self, main_button):
|
||||||
logging.debug("Pick prouter option")
|
logging.debug("Pick prouter option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.PROUTER.value))
|
main_button.configure(image=Images.get(ImageEnum.PROUTER))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.PROUTER.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.PROUTER)
|
||||||
self.canvas.draw_node_name = "prouter"
|
self.canvas.draw_node_name = "prouter"
|
||||||
|
|
||||||
def pick_ovs(self, main_button):
|
def pick_ovs(self, main_button):
|
||||||
logging.debug("Pick OVS option")
|
logging.debug("Pick OVS option")
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.OVS.value))
|
main_button.configure(image=Images.get(ImageEnum.OVS))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.OVS.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.OVS)
|
||||||
self.canvas.draw_node_name = "OVS"
|
self.canvas.draw_node_name = "OVS"
|
||||||
|
|
||||||
# TODO what graph node is this
|
# TODO what graph node is this
|
||||||
def pick_editnode(self, main_button):
|
def pick_editnode(self, main_button):
|
||||||
self.network_layer_option_menu.destroy()
|
self.network_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.EDITNODE.value))
|
main_button.configure(image=Images.get(ImageEnum.EDITNODE))
|
||||||
logging.debug("Pick editnode option")
|
logging.debug("Pick editnode option")
|
||||||
|
|
||||||
def draw_network_layer_options(self, network_layer_button):
|
def draw_network_layer_options(self, network_layer_button):
|
||||||
|
@ -262,13 +262,13 @@ class CoreToolbar(object):
|
||||||
self.destroy_previous_frame()
|
self.destroy_previous_frame()
|
||||||
option_frame = tk.Frame(self.master, padx=1, pady=1)
|
option_frame = tk.Frame(self.master, padx=1, pady=1)
|
||||||
img_list = [
|
img_list = [
|
||||||
Images.get(ImageEnum.ROUTER.value),
|
Images.get(ImageEnum.ROUTER),
|
||||||
Images.get(ImageEnum.HOST.value),
|
Images.get(ImageEnum.HOST),
|
||||||
Images.get(ImageEnum.PC.value),
|
Images.get(ImageEnum.PC),
|
||||||
Images.get(ImageEnum.MDR.value),
|
Images.get(ImageEnum.MDR),
|
||||||
Images.get(ImageEnum.PROUTER.value),
|
Images.get(ImageEnum.PROUTER),
|
||||||
Images.get(ImageEnum.OVS.value),
|
Images.get(ImageEnum.OVS),
|
||||||
Images.get(ImageEnum.EDITNODE.value),
|
Images.get(ImageEnum.EDITNODE),
|
||||||
]
|
]
|
||||||
func_list = [
|
func_list = [
|
||||||
self.pick_router,
|
self.pick_router,
|
||||||
|
@ -312,7 +312,7 @@ class CoreToolbar(object):
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
router_image = Images.get(ImageEnum.ROUTER.value)
|
router_image = Images.get(ImageEnum.ROUTER)
|
||||||
network_layer_button = tk.Radiobutton(
|
network_layer_button = tk.Radiobutton(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
indicatoron=False,
|
indicatoron=False,
|
||||||
|
@ -329,41 +329,41 @@ class CoreToolbar(object):
|
||||||
def pick_hub(self, main_button):
|
def pick_hub(self, main_button):
|
||||||
logging.debug("Pick link-layer node HUB")
|
logging.debug("Pick link-layer node HUB")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.HUB.value))
|
main_button.configure(image=Images.get(ImageEnum.HUB))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.HUB.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.HUB)
|
||||||
self.canvas.draw_node_name = "hub"
|
self.canvas.draw_node_name = "hub"
|
||||||
|
|
||||||
def pick_switch(self, main_button):
|
def pick_switch(self, main_button):
|
||||||
logging.debug("Pick link-layer node SWITCH")
|
logging.debug("Pick link-layer node SWITCH")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.SWITCH.value))
|
main_button.configure(image=Images.get(ImageEnum.SWITCH))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.SWITCH.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.SWITCH)
|
||||||
self.canvas.draw_node_name = "switch"
|
self.canvas.draw_node_name = "switch"
|
||||||
|
|
||||||
def pick_wlan(self, main_button):
|
def pick_wlan(self, main_button):
|
||||||
logging.debug("Pick link-layer node WLAN")
|
logging.debug("Pick link-layer node WLAN")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.WLAN.value))
|
main_button.configure(image=Images.get(ImageEnum.WLAN))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.WLAN.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.WLAN)
|
||||||
self.canvas.draw_node_name = "wlan"
|
self.canvas.draw_node_name = "wlan"
|
||||||
|
|
||||||
def pick_rj45(self, main_button):
|
def pick_rj45(self, main_button):
|
||||||
logging.debug("Pick link-layer node RJ45")
|
logging.debug("Pick link-layer node RJ45")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.RJ45.value))
|
main_button.configure(image=Images.get(ImageEnum.RJ45))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.RJ45.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.RJ45)
|
||||||
self.canvas.draw_node_name = "rj45"
|
self.canvas.draw_node_name = "rj45"
|
||||||
|
|
||||||
def pick_tunnel(self, main_button):
|
def pick_tunnel(self, main_button):
|
||||||
logging.debug("Pick link-layer node TUNNEL")
|
logging.debug("Pick link-layer node TUNNEL")
|
||||||
self.link_layer_option_menu.destroy()
|
self.link_layer_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.TUNNEL.value))
|
main_button.configure(image=Images.get(ImageEnum.TUNNEL))
|
||||||
self.canvas.mode = GraphMode.PICKNODE
|
self.canvas.mode = GraphMode.PICKNODE
|
||||||
self.canvas.draw_node_image = Images.get(ImageEnum.TUNNEL.value)
|
self.canvas.draw_node_image = Images.get(ImageEnum.TUNNEL)
|
||||||
self.canvas.draw_node_name = "tunnel"
|
self.canvas.draw_node_name = "tunnel"
|
||||||
|
|
||||||
def pick_emane(self, main_button):
|
def pick_emane(self, main_button):
|
||||||
|
@ -431,7 +431,7 @@ class CoreToolbar(object):
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
hub_image = Images.get(ImageEnum.HUB.value)
|
hub_image = Images.get(ImageEnum.HUB)
|
||||||
link_layer_button = tk.Radiobutton(
|
link_layer_button = tk.Radiobutton(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
indicatoron=False,
|
indicatoron=False,
|
||||||
|
@ -447,22 +447,22 @@ class CoreToolbar(object):
|
||||||
|
|
||||||
def pick_marker(self, main_button):
|
def pick_marker(self, main_button):
|
||||||
self.marker_option_menu.destroy()
|
self.marker_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.MARKER.value))
|
main_button.configure(image=Images.get(ImageEnum.MARKER))
|
||||||
logging.debug("Pick MARKER")
|
logging.debug("Pick MARKER")
|
||||||
|
|
||||||
def pick_oval(self, main_button):
|
def pick_oval(self, main_button):
|
||||||
self.marker_option_menu.destroy()
|
self.marker_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.OVAL.value))
|
main_button.configure(image=Images.get(ImageEnum.OVAL))
|
||||||
logging.debug("Pick OVAL")
|
logging.debug("Pick OVAL")
|
||||||
|
|
||||||
def pick_rectangle(self, main_button):
|
def pick_rectangle(self, main_button):
|
||||||
self.marker_option_menu.destroy()
|
self.marker_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.RECTANGLE.value))
|
main_button.configure(image=Images.get(ImageEnum.RECTANGLE))
|
||||||
logging.debug("Pick RECTANGLE")
|
logging.debug("Pick RECTANGLE")
|
||||||
|
|
||||||
def pick_text(self, main_button):
|
def pick_text(self, main_button):
|
||||||
self.marker_option_menu.destroy()
|
self.marker_option_menu.destroy()
|
||||||
main_button.configure(image=Images.get(ImageEnum.TEXT.value))
|
main_button.configure(image=Images.get(ImageEnum.TEXT))
|
||||||
logging.debug("Pick TEXT")
|
logging.debug("Pick TEXT")
|
||||||
|
|
||||||
def draw_marker_options(self, main_button):
|
def draw_marker_options(self, main_button):
|
||||||
|
@ -476,10 +476,10 @@ class CoreToolbar(object):
|
||||||
self.destroy_previous_frame()
|
self.destroy_previous_frame()
|
||||||
option_frame = tk.Frame(self.master, padx=1, pady=1)
|
option_frame = tk.Frame(self.master, padx=1, pady=1)
|
||||||
img_list = [
|
img_list = [
|
||||||
Images.get(ImageEnum.MARKER.value),
|
Images.get(ImageEnum.MARKER),
|
||||||
Images.get(ImageEnum.OVAL.value),
|
Images.get(ImageEnum.OVAL),
|
||||||
Images.get(ImageEnum.RECTANGLE.value),
|
Images.get(ImageEnum.RECTANGLE),
|
||||||
Images.get(ImageEnum.TEXT.value),
|
Images.get(ImageEnum.TEXT),
|
||||||
]
|
]
|
||||||
func_list = [
|
func_list = [
|
||||||
self.pick_marker,
|
self.pick_marker,
|
||||||
|
@ -508,7 +508,7 @@ class CoreToolbar(object):
|
||||||
|
|
||||||
:return: nothing
|
:return: nothing
|
||||||
"""
|
"""
|
||||||
marker_image = Images.get(ImageEnum.MARKER.value)
|
marker_image = Images.get(ImageEnum.MARKER)
|
||||||
marker_main_button = tk.Radiobutton(
|
marker_main_button = tk.Radiobutton(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
indicatoron=False,
|
indicatoron=False,
|
||||||
|
@ -530,13 +530,13 @@ class CoreToolbar(object):
|
||||||
"""
|
"""
|
||||||
self.create_regular_button(
|
self.create_regular_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.START.value),
|
Images.get(ImageEnum.START),
|
||||||
self.click_start_session_tool,
|
self.click_start_session_tool,
|
||||||
"start the session",
|
"start the session",
|
||||||
)
|
)
|
||||||
self.create_radio_button(
|
self.create_radio_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.SELECT.value),
|
Images.get(ImageEnum.SELECT),
|
||||||
self.click_selection_tool,
|
self.click_selection_tool,
|
||||||
self.radio_value,
|
self.radio_value,
|
||||||
1,
|
1,
|
||||||
|
@ -544,7 +544,7 @@ class CoreToolbar(object):
|
||||||
)
|
)
|
||||||
self.create_radio_button(
|
self.create_radio_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.LINK.value),
|
Images.get(ImageEnum.LINK),
|
||||||
self.click_link_tool,
|
self.click_link_tool,
|
||||||
self.radio_value,
|
self.radio_value,
|
||||||
2,
|
2,
|
||||||
|
@ -558,7 +558,7 @@ class CoreToolbar(object):
|
||||||
def create_observe_button(self):
|
def create_observe_button(self):
|
||||||
menu_button = tk.Menubutton(
|
menu_button = tk.Menubutton(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
image=Images.get(ImageEnum.OBSERVE.value),
|
image=Images.get(ImageEnum.OBSERVE),
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=self.height,
|
height=self.height,
|
||||||
direction=tk.RIGHT,
|
direction=tk.RIGHT,
|
||||||
|
@ -615,13 +615,13 @@ class CoreToolbar(object):
|
||||||
def create_runtime_toolbar(self):
|
def create_runtime_toolbar(self):
|
||||||
self.create_regular_button(
|
self.create_regular_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.STOP.value),
|
Images.get(ImageEnum.STOP),
|
||||||
self.click_stop_button,
|
self.click_stop_button,
|
||||||
"stop the session",
|
"stop the session",
|
||||||
)
|
)
|
||||||
self.create_radio_button(
|
self.create_radio_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.SELECT.value),
|
Images.get(ImageEnum.SELECT),
|
||||||
self.click_selection_tool,
|
self.click_selection_tool,
|
||||||
self.exec_radio_value,
|
self.exec_radio_value,
|
||||||
1,
|
1,
|
||||||
|
@ -630,7 +630,7 @@ class CoreToolbar(object):
|
||||||
self.create_observe_button()
|
self.create_observe_button()
|
||||||
self.create_radio_button(
|
self.create_radio_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.PLOT.value),
|
Images.get(ImageEnum.PLOT),
|
||||||
self.click_plot_button,
|
self.click_plot_button,
|
||||||
self.exec_radio_value,
|
self.exec_radio_value,
|
||||||
2,
|
2,
|
||||||
|
@ -638,7 +638,7 @@ class CoreToolbar(object):
|
||||||
)
|
)
|
||||||
self.create_radio_button(
|
self.create_radio_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.MARKER.value),
|
Images.get(ImageEnum.MARKER),
|
||||||
self.click_marker_button,
|
self.click_marker_button,
|
||||||
self.exec_radio_value,
|
self.exec_radio_value,
|
||||||
3,
|
3,
|
||||||
|
@ -646,16 +646,13 @@ class CoreToolbar(object):
|
||||||
)
|
)
|
||||||
self.create_radio_button(
|
self.create_radio_button(
|
||||||
self.edit_frame,
|
self.edit_frame,
|
||||||
Images.get(ImageEnum.TWONODE.value),
|
Images.get(ImageEnum.TWONODE),
|
||||||
self.click_two_node_button,
|
self.click_two_node_button,
|
||||||
self.exec_radio_value,
|
self.exec_radio_value,
|
||||||
4,
|
4,
|
||||||
"run command from one node to another",
|
"run command from one node to another",
|
||||||
)
|
)
|
||||||
self.create_regular_button(
|
self.create_regular_button(
|
||||||
self.edit_frame,
|
self.edit_frame, Images.get(ImageEnum.RUN), self.click_run_button, "run"
|
||||||
Images.get(ImageEnum.RUN.value),
|
|
||||||
self.click_run_button,
|
|
||||||
"run",
|
|
||||||
)
|
)
|
||||||
self.exec_radio_value.set(1)
|
self.exec_radio_value.set(1)
|
||||||
|
|
0
coretk/coretk/dialogs/__init__.py
Normal file
0
coretk/coretk/dialogs/__init__.py
Normal file
24
coretk/coretk/dialogs/dialog.py
Normal file
24
coretk/coretk/dialogs/dialog.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import tkinter as tk
|
||||||
|
|
||||||
|
from coretk.images import ImageEnum, Images
|
||||||
|
|
||||||
|
|
||||||
|
class Dialog(tk.Toplevel):
|
||||||
|
def __init__(self, master, app, title, modal=False):
|
||||||
|
super().__init__(master, padx=5, pady=5)
|
||||||
|
self.withdraw()
|
||||||
|
self.app = app
|
||||||
|
self.modal = modal
|
||||||
|
self.title(title)
|
||||||
|
self.protocol("WM_DELETE_WINDOW", self.destroy)
|
||||||
|
image = Images.get(ImageEnum.CORE)
|
||||||
|
self.tk.call("wm", "iconphoto", self._w, image)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
self.transient(self.master)
|
||||||
|
self.focus_force()
|
||||||
|
if self.modal:
|
||||||
|
self.grab_set()
|
||||||
|
self.update()
|
||||||
|
self.deiconify()
|
||||||
|
self.wait_window()
|
34
coretk/coretk/dialogs/sessionoptions.py
Normal file
34
coretk/coretk/dialogs/sessionoptions.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import logging
|
||||||
|
import tkinter as tk
|
||||||
|
|
||||||
|
from coretk import configutils
|
||||||
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
|
||||||
|
PAD_X = 2
|
||||||
|
PAD_Y = 2
|
||||||
|
|
||||||
|
|
||||||
|
class SessionOptionsDialog(Dialog):
|
||||||
|
def __init__(self, master, app):
|
||||||
|
super().__init__(master, app, "Session Options", modal=True)
|
||||||
|
self.options = None
|
||||||
|
self.values = None
|
||||||
|
self.save_button = tk.Button(self, text="Save", command=self.save)
|
||||||
|
self.cancel_button = tk.Button(self, text="Cancel", command=self.destroy)
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
session_id = self.master.core_grpc.session_id
|
||||||
|
response = self.master.core_grpc.core.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)
|
||||||
|
self.save_button.grid(row=1, pady=PAD_Y, padx=PAD_X, sticky="ew")
|
||||||
|
self.cancel_button.grid(row=1, column=1, pady=PAD_Y, padx=PAD_X, sticky="ew")
|
||||||
|
|
||||||
|
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)
|
||||||
|
logging.info("saved session config: %s", response)
|
||||||
|
self.destroy()
|
159
coretk/coretk/dialogs/sessions.py
Normal file
159
coretk/coretk/dialogs/sessions.py
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
import logging
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter.ttk import Scrollbar, Treeview
|
||||||
|
|
||||||
|
from core.api.grpc import core_pb2
|
||||||
|
from coretk.dialogs.dialog import Dialog
|
||||||
|
from coretk.images import ImageEnum, Images
|
||||||
|
|
||||||
|
|
||||||
|
class SessionsDialog(Dialog):
|
||||||
|
def __init__(self, master, app):
|
||||||
|
"""
|
||||||
|
create session table instance
|
||||||
|
|
||||||
|
:param coretk.coregrpc.CoreGrpc grpc: coregrpc
|
||||||
|
:param root.master master:
|
||||||
|
"""
|
||||||
|
super().__init__(master, app, "Sessions", modal=True)
|
||||||
|
self.selected = False
|
||||||
|
self.selected_id = None
|
||||||
|
self.tree = None
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
self.draw_description()
|
||||||
|
self.draw_tree()
|
||||||
|
self.draw_buttons()
|
||||||
|
|
||||||
|
def draw_description(self):
|
||||||
|
"""
|
||||||
|
write a short description
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
label = tk.Label(
|
||||||
|
self,
|
||||||
|
text="Below is a list of active CORE sessions. Double-click to \n"
|
||||||
|
"connect to an existing session. Usually, only sessions in \n"
|
||||||
|
"the RUNTIME state persist in the daemon, except for the \n"
|
||||||
|
"one you might be concurrently editting.",
|
||||||
|
)
|
||||||
|
label.grid(row=0, sticky="ew", pady=5)
|
||||||
|
|
||||||
|
def draw_tree(self):
|
||||||
|
self.tree = Treeview(self, columns=("id", "state", "nodes"), show="headings")
|
||||||
|
self.tree.grid(row=1, sticky="nsew")
|
||||||
|
self.tree.column("id", stretch=tk.YES)
|
||||||
|
self.tree.heading("id", text="ID")
|
||||||
|
self.tree.column("state", stretch=tk.YES)
|
||||||
|
self.tree.heading("state", text="State")
|
||||||
|
self.tree.column("nodes", stretch=tk.YES)
|
||||||
|
self.tree.heading("nodes", text="Node Count")
|
||||||
|
|
||||||
|
response = self.app.core_grpc.core.get_sessions()
|
||||||
|
logging.info("sessions: %s", response)
|
||||||
|
for index, session in enumerate(response.sessions):
|
||||||
|
state_name = core_pb2.SessionState.Enum.Name(session.state)
|
||||||
|
self.tree.insert(
|
||||||
|
"",
|
||||||
|
tk.END,
|
||||||
|
text=str(session.id),
|
||||||
|
values=(session.id, state_name, session.nodes),
|
||||||
|
)
|
||||||
|
self.tree.bind("<Double-1>", self.on_selected)
|
||||||
|
self.tree.bind("<<TreeviewSelect>>", self.click_select)
|
||||||
|
|
||||||
|
yscrollbar = Scrollbar(self, orient="vertical", command=self.tree.yview)
|
||||||
|
yscrollbar.grid(row=1, column=1, sticky="ns")
|
||||||
|
self.tree.configure(yscrollcommand=yscrollbar.set)
|
||||||
|
|
||||||
|
xscrollbar = Scrollbar(self, orient="horizontal", command=self.tree.xview)
|
||||||
|
xscrollbar.grid(row=2, sticky="ew", pady=5)
|
||||||
|
self.tree.configure(xscrollcommand=xscrollbar.set)
|
||||||
|
|
||||||
|
def draw_buttons(self):
|
||||||
|
frame = tk.Frame(self)
|
||||||
|
for i in range(4):
|
||||||
|
frame.columnconfigure(i, weight=1)
|
||||||
|
frame.grid(row=3, sticky="ew")
|
||||||
|
b = tk.Button(
|
||||||
|
frame,
|
||||||
|
image=Images.get(ImageEnum.DOCUMENTNEW),
|
||||||
|
text="New",
|
||||||
|
compound=tk.LEFT,
|
||||||
|
command=self.click_new,
|
||||||
|
)
|
||||||
|
b.grid(row=0, padx=2, sticky="ew")
|
||||||
|
b = tk.Button(
|
||||||
|
frame,
|
||||||
|
image=Images.get(ImageEnum.FILEOPEN),
|
||||||
|
text="Connect",
|
||||||
|
compound=tk.LEFT,
|
||||||
|
command=self.click_connect,
|
||||||
|
)
|
||||||
|
b.grid(row=0, column=1, padx=2, sticky="ew")
|
||||||
|
b = tk.Button(
|
||||||
|
frame,
|
||||||
|
image=Images.get(ImageEnum.EDITDELETE),
|
||||||
|
text="Shutdown",
|
||||||
|
compound=tk.LEFT,
|
||||||
|
command=self.click_shutdown,
|
||||||
|
)
|
||||||
|
b.grid(row=0, column=2, padx=2, sticky="ew")
|
||||||
|
b = tk.Button(frame, text="Cancel", command=self.click_new)
|
||||||
|
b.grid(row=0, column=3, padx=2, sticky="ew")
|
||||||
|
|
||||||
|
def click_new(self):
|
||||||
|
self.app.core_grpc.create_new_session()
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
def click_select(self, event):
|
||||||
|
item = self.tree.selection()
|
||||||
|
session_id = int(self.tree.item(item, "text"))
|
||||||
|
self.selected = True
|
||||||
|
self.selected_id = session_id
|
||||||
|
|
||||||
|
def click_connect(self):
|
||||||
|
"""
|
||||||
|
if no session is selected yet, create a new one else join that session
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if self.selected and self.selected_id is not None:
|
||||||
|
self.join_session(self.selected_id)
|
||||||
|
elif not self.selected and self.selected_id is None:
|
||||||
|
self.click_new()
|
||||||
|
else:
|
||||||
|
logging.error("sessions invalid state")
|
||||||
|
|
||||||
|
def click_shutdown(self):
|
||||||
|
"""
|
||||||
|
if no session is currently selected create a new session else shut the selected
|
||||||
|
session down.
|
||||||
|
|
||||||
|
:return: nothing
|
||||||
|
"""
|
||||||
|
if self.selected and self.selected_id is not None:
|
||||||
|
self.shutdown_session(self.selected_id)
|
||||||
|
elif not self.selected and self.selected_id is None:
|
||||||
|
self.click_new()
|
||||||
|
else:
|
||||||
|
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.destroy()
|
||||||
|
|
||||||
|
def on_selected(self, event):
|
||||||
|
item = self.tree.selection()
|
||||||
|
sid = int(self.tree.item(item, "text"))
|
||||||
|
self.join_session(sid)
|
||||||
|
|
||||||
|
def shutdown_session(self, sid):
|
||||||
|
self.app.core_grpc.terminate_session(sid)
|
||||||
|
self.click_new()
|
||||||
|
self.destroy()
|
|
@ -94,7 +94,7 @@ class WlanAntennaManager:
|
||||||
x - 16 + self.offset,
|
x - 16 + self.offset,
|
||||||
y - 16,
|
y - 16,
|
||||||
anchor=tk.CENTER,
|
anchor=tk.CENTER,
|
||||||
image=Images.get(ImageEnum.ANTENNA.value),
|
image=Images.get(ImageEnum.ANTENNA),
|
||||||
tags="antenna",
|
tags="antenna",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,8 +21,8 @@ class Images:
|
||||||
cls.images[name] = tk_image
|
cls.images[name] = tk_image
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, name):
|
def get(cls, image):
|
||||||
return cls.images[name]
|
return cls.images[image.value]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def convert_type_and_model_to_image(cls, node_type, node_model):
|
def convert_type_and_model_to_image(cls, node_type, node_model):
|
||||||
|
@ -35,30 +35,31 @@ class Images:
|
||||||
:return: the matching image and its name
|
:return: the matching image and its name
|
||||||
"""
|
"""
|
||||||
if node_type == core_pb2.NodeType.SWITCH:
|
if node_type == core_pb2.NodeType.SWITCH:
|
||||||
return Images.get(ImageEnum.SWITCH.value), "switch"
|
return Images.get(ImageEnum.SWITCH), "switch"
|
||||||
if node_type == core_pb2.NodeType.HUB:
|
if node_type == core_pb2.NodeType.HUB:
|
||||||
return Images.get(ImageEnum.HUB.value), "hub"
|
return Images.get(ImageEnum.HUB), "hub"
|
||||||
if node_type == core_pb2.NodeType.WIRELESS_LAN:
|
if node_type == core_pb2.NodeType.WIRELESS_LAN:
|
||||||
return Images.get(ImageEnum.WLAN.value), "wlan"
|
return Images.get(ImageEnum.WLAN.value), "wlan"
|
||||||
if node_type == core_pb2.NodeType.EMANE:
|
if node_type == core_pb2.NodeType.EMANE:
|
||||||
return Images.get(ImageEnum.EMANE.value), "emane"
|
return Images.get(ImageEnum.EMANE.value), "emane"
|
||||||
|
|
||||||
if node_type == core_pb2.NodeType.RJ45:
|
if node_type == core_pb2.NodeType.RJ45:
|
||||||
return Images.get(ImageEnum.RJ45.value), "rj45"
|
return Images.get(ImageEnum.RJ45), "rj45"
|
||||||
if node_type == core_pb2.NodeType.TUNNEL:
|
if node_type == core_pb2.NodeType.TUNNEL:
|
||||||
return Images.get(ImageEnum.TUNNEL.value), "tunnel"
|
return Images.get(ImageEnum.TUNNEL), "tunnel"
|
||||||
if node_type == core_pb2.NodeType.DEFAULT:
|
if node_type == core_pb2.NodeType.DEFAULT:
|
||||||
if node_model == "router":
|
if node_model == "router":
|
||||||
return Images.get(ImageEnum.ROUTER.value), "router"
|
return Images.get(ImageEnum.ROUTER), "router"
|
||||||
if node_model == "host":
|
if node_model == "host":
|
||||||
return Images.get((ImageEnum.HOST.value)), "host"
|
return Images.get(ImageEnum.HOST), "host"
|
||||||
if node_model == "PC":
|
if node_model == "PC":
|
||||||
return Images.get(ImageEnum.PC.value), "PC"
|
return Images.get(ImageEnum.PC), "PC"
|
||||||
if node_model == "mdr":
|
if node_model == "mdr":
|
||||||
return Images.get(ImageEnum.MDR.value), "mdr"
|
return Images.get(ImageEnum.MDR), "mdr"
|
||||||
if node_model == "prouter":
|
if node_model == "prouter":
|
||||||
return Images.get(ImageEnum.PROUTER.value), "prouter"
|
return Images.get(ImageEnum.PROUTER), "prouter"
|
||||||
if node_model == "OVS":
|
if node_model == "OVS":
|
||||||
return Images.get(ImageEnum.OVS.value), "ovs"
|
return Images.get(ImageEnum.OVS), "ovs"
|
||||||
else:
|
else:
|
||||||
logging.debug("INVALID INPUT OR NOT CONSIDERED YET")
|
logging.debug("INVALID INPUT OR NOT CONSIDERED YET")
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import webbrowser
|
||||||
from tkinter import filedialog, messagebox
|
from tkinter import filedialog, messagebox
|
||||||
|
|
||||||
from core.api.grpc import core_pb2
|
from core.api.grpc import core_pb2
|
||||||
|
from coretk.dialogs.sessionoptions import SessionOptionsDialog
|
||||||
|
from coretk.dialogs.sessions import SessionsDialog
|
||||||
from coretk.setwallpaper import CanvasWallpaper
|
from coretk.setwallpaper import CanvasWallpaper
|
||||||
from coretk.sizeandscale import SizeAndScale
|
from coretk.sizeandscale import SizeAndScale
|
||||||
|
|
||||||
|
@ -290,10 +292,6 @@ def widgets_configure_throughput():
|
||||||
logging.debug("Click widgets configure throughput")
|
logging.debug("Click widgets configure throughput")
|
||||||
|
|
||||||
|
|
||||||
def session_change_sessions():
|
|
||||||
logging.debug("Click session change sessions")
|
|
||||||
|
|
||||||
|
|
||||||
def session_node_types():
|
def session_node_types():
|
||||||
logging.debug("Click session node types")
|
logging.debug("Click session node types")
|
||||||
|
|
||||||
|
@ -314,10 +312,6 @@ def session_emulation_servers():
|
||||||
logging.debug("Click session emulation servers")
|
logging.debug("Click session emulation servers")
|
||||||
|
|
||||||
|
|
||||||
def session_options():
|
|
||||||
logging.debug("Click session options")
|
|
||||||
|
|
||||||
|
|
||||||
def help_about():
|
def help_about():
|
||||||
logging.debug("Click help About")
|
logging.debug("Click help About")
|
||||||
|
|
||||||
|
@ -429,3 +423,13 @@ class MenuAction:
|
||||||
|
|
||||||
def help_core_documentation(self):
|
def help_core_documentation(self):
|
||||||
webbrowser.open_new("http://coreemu.github.io/core/")
|
webbrowser.open_new("http://coreemu.github.io/core/")
|
||||||
|
|
||||||
|
def session_options(self):
|
||||||
|
logging.debug("Click session options")
|
||||||
|
dialog = SessionOptionsDialog(self.application, self.application)
|
||||||
|
dialog.show()
|
||||||
|
|
||||||
|
def session_change_sessions(self):
|
||||||
|
logging.debug("Click session change sessions")
|
||||||
|
dialog = SessionsDialog(self.application, self.application)
|
||||||
|
dialog.show()
|
||||||
|
|
|
@ -1,183 +0,0 @@
|
||||||
import logging
|
|
||||||
import tkinter as tk
|
|
||||||
from tkinter.ttk import Scrollbar, Treeview
|
|
||||||
|
|
||||||
from coretk.images import ImageEnum, Images
|
|
||||||
|
|
||||||
|
|
||||||
class SessionTable:
|
|
||||||
def __init__(self, grpc, master):
|
|
||||||
"""
|
|
||||||
create session table instance
|
|
||||||
:param coretk.coregrpc.CoreGrpc grpc: coregrpc
|
|
||||||
:param root.master master:
|
|
||||||
"""
|
|
||||||
self.grpc = grpc
|
|
||||||
self.selected = False
|
|
||||||
self.selected_sid = None
|
|
||||||
self.master = master
|
|
||||||
self.top = tk.Toplevel(self.master)
|
|
||||||
self.description_definition()
|
|
||||||
self.top.title("CORE sessions")
|
|
||||||
|
|
||||||
self.tree = Treeview(self.top)
|
|
||||||
# self.tree.pack(side=tk.TOP)
|
|
||||||
self.tree.grid(row=1, column=0, columnspan=2)
|
|
||||||
self.draw_scrollbar()
|
|
||||||
self.draw()
|
|
||||||
|
|
||||||
def description_definition(self):
|
|
||||||
"""
|
|
||||||
write a short description
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
lable = tk.Label(
|
|
||||||
self.top,
|
|
||||||
text="Below is a list of active CORE sessions. Double-click to "
|
|
||||||
"\nconnect to an existing session. Usually, only sessions in "
|
|
||||||
"\nthe RUNTIME state persist in the daemon, except for the "
|
|
||||||
"\none you might be concurrently editting.",
|
|
||||||
)
|
|
||||||
lable.grid(sticky=tk.W)
|
|
||||||
|
|
||||||
def column_definition(self):
|
|
||||||
# self.tree["columns"] = ("name", "nodecount", "filename", "date")
|
|
||||||
self.tree["columns"] = "nodecount"
|
|
||||||
self.tree.column("#0", width=300, minwidth=30)
|
|
||||||
# self.tree.column("name", width=72, miwidth=30)
|
|
||||||
self.tree.column("nodecount", width=300, minwidth=30)
|
|
||||||
# self.tree.column("filename", width=92, minwidth=30)
|
|
||||||
# self.tree.column("date", width=170, minwidth=30)
|
|
||||||
|
|
||||||
def draw_scrollbar(self):
|
|
||||||
yscrollbar = Scrollbar(self.top, orient="vertical", command=self.tree.yview)
|
|
||||||
yscrollbar.grid(row=1, column=3, sticky=tk.N + tk.S + tk.W)
|
|
||||||
self.tree.configure(yscrollcommand=yscrollbar.set)
|
|
||||||
|
|
||||||
xscrollbar = Scrollbar(self.top, orient="horizontal", command=self.tree.xview)
|
|
||||||
xscrollbar.grid(row=2, columnspan=2, sticky=tk.E + tk.W + tk.S)
|
|
||||||
self.tree.configure(xscrollcommand=xscrollbar.set)
|
|
||||||
|
|
||||||
def heading_definition(self):
|
|
||||||
self.tree.heading("#0", text="ID", anchor=tk.W)
|
|
||||||
# self.tree.heading("name", text="Name", anchor=tk.CENTER)
|
|
||||||
self.tree.heading("nodecount", text="Node Count", anchor=tk.W)
|
|
||||||
# self.tree.heading("filename", text="Filename", anchor=tk.CENTER)
|
|
||||||
# self.tree.heading("date", text="Date", anchor=tk.CENTER)
|
|
||||||
|
|
||||||
def enter_session(self, sid):
|
|
||||||
self.top.destroy()
|
|
||||||
response = self.grpc.core.get_session(sid)
|
|
||||||
self.grpc.session_id = sid
|
|
||||||
self.grpc.core.events(sid, self.grpc.log_event)
|
|
||||||
logging.info("Entering session_id %s.... Result: %s", sid, response)
|
|
||||||
|
|
||||||
def new_session(self):
|
|
||||||
self.top.destroy()
|
|
||||||
self.grpc.create_new_session()
|
|
||||||
|
|
||||||
def on_selected(self, event):
|
|
||||||
item = self.tree.selection()
|
|
||||||
sid = int(self.tree.item(item, "text"))
|
|
||||||
self.enter_session(sid)
|
|
||||||
|
|
||||||
def click_select(self, event):
|
|
||||||
# logging.debug("Click on %s ", event)
|
|
||||||
item = self.tree.selection()
|
|
||||||
sid = int(self.tree.item(item, "text"))
|
|
||||||
self.selected = True
|
|
||||||
self.selected_sid = sid
|
|
||||||
|
|
||||||
def session_definition(self):
|
|
||||||
response = self.grpc.core.get_sessions()
|
|
||||||
# logging.info("querysessiondrawing.py Get all sessions %s", response)
|
|
||||||
index = 1
|
|
||||||
for session in response.sessions:
|
|
||||||
self.tree.insert(
|
|
||||||
"", index, None, text=str(session.id), values=(str(session.nodes))
|
|
||||||
)
|
|
||||||
index = index + 1
|
|
||||||
self.tree.bind("<Double-1>", self.on_selected)
|
|
||||||
self.tree.bind("<<TreeviewSelect>>", self.click_select)
|
|
||||||
|
|
||||||
def click_connect(self):
|
|
||||||
"""
|
|
||||||
if no session is selected yet, create a new one else join that session
|
|
||||||
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
if self.selected and self.selected_sid is not None:
|
|
||||||
self.enter_session(self.selected_sid)
|
|
||||||
elif not self.selected and self.selected_sid is None:
|
|
||||||
self.new_session()
|
|
||||||
else:
|
|
||||||
logging.error("querysessiondrawing.py invalid state")
|
|
||||||
|
|
||||||
def shutdown_session(self, sid):
|
|
||||||
self.grpc.terminate_session(sid)
|
|
||||||
self.new_session()
|
|
||||||
self.top.destroy()
|
|
||||||
|
|
||||||
def click_shutdown(self):
|
|
||||||
"""
|
|
||||||
if no session is currently selected create a new session else shut the selected session down
|
|
||||||
|
|
||||||
:return: nothing
|
|
||||||
"""
|
|
||||||
if self.selected and self.selected_sid is not None:
|
|
||||||
self.shutdown_session(self.selected_sid)
|
|
||||||
elif not self.selected and self.selected_sid is None:
|
|
||||||
self.new_session()
|
|
||||||
else:
|
|
||||||
logging.error("querysessiondrawing.py invalid state")
|
|
||||||
# if self.selected and self.selected_sid is not None:
|
|
||||||
|
|
||||||
def draw_buttons(self):
|
|
||||||
f = tk.Frame(self.top)
|
|
||||||
f.grid(row=3, sticky=tk.W)
|
|
||||||
|
|
||||||
b = tk.Button(
|
|
||||||
f,
|
|
||||||
image=Images.get(ImageEnum.DOCUMENTNEW.value),
|
|
||||||
text="New",
|
|
||||||
compound=tk.LEFT,
|
|
||||||
command=self.new_session,
|
|
||||||
)
|
|
||||||
b.pack(side=tk.LEFT, padx=3, pady=4)
|
|
||||||
b = tk.Button(
|
|
||||||
f,
|
|
||||||
image=Images.get(ImageEnum.FILEOPEN.value),
|
|
||||||
text="Connect",
|
|
||||||
compound=tk.LEFT,
|
|
||||||
command=self.click_connect,
|
|
||||||
)
|
|
||||||
b.pack(side=tk.LEFT, padx=3, pady=4)
|
|
||||||
b = tk.Button(
|
|
||||||
f,
|
|
||||||
image=Images.get(ImageEnum.EDITDELETE.value),
|
|
||||||
text="Shutdown",
|
|
||||||
compound=tk.LEFT,
|
|
||||||
command=self.click_shutdown,
|
|
||||||
)
|
|
||||||
b.pack(side=tk.LEFT, padx=3, pady=4)
|
|
||||||
b = tk.Button(f, text="Cancel", command=self.new_session)
|
|
||||||
b.pack(side=tk.LEFT, padx=3, pady=4)
|
|
||||||
|
|
||||||
def center(self):
|
|
||||||
window_width = self.master.winfo_width()
|
|
||||||
window_height = self.master.winfo_height()
|
|
||||||
self.top.update()
|
|
||||||
top_level_width = self.top.winfo_width()
|
|
||||||
top_level_height = self.top.winfo_height()
|
|
||||||
x = window_width / 2 - top_level_width / 2
|
|
||||||
y = window_height / 2 - top_level_height / 2
|
|
||||||
|
|
||||||
self.top.geometry("+%d+%d" % (x, y))
|
|
||||||
|
|
||||||
def draw(self):
|
|
||||||
self.column_definition()
|
|
||||||
self.heading_definition()
|
|
||||||
self.session_definition()
|
|
||||||
self.draw_buttons()
|
|
||||||
self.center()
|
|
||||||
self.top.wait_window()
|
|
Loading…
Reference in a new issue