Merge pull request #436 from coreemu/pygui-runtool

Pygui runtool
This commit is contained in:
bharnden 2020-04-22 23:28:47 -07:00 committed by GitHub
commit a662fcc62c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 1 deletions

View file

@ -0,0 +1,123 @@
import tkinter as tk
from tkinter import ttk
from core.api.grpc import core_pb2
from core.gui.dialogs.dialog import Dialog
from core.gui.themes import FRAME_PAD, PADY
from core.gui.widgets import CodeText, ListboxScroll
class RunToolDialog(Dialog):
def __init__(self, master, app):
super().__init__(master, app, "Run Tool", modal=True)
self.cmd = tk.StringVar(value="ps ax")
self.app = app
self.result = None
self.node_list = None
self.executable_nodes = {}
self.store_nodes()
self.draw()
def store_nodes(self):
"""
store all CORE nodes (nodes that execute commands) from all existing nodes
"""
for nid, node in self.app.core.canvas_nodes.items():
if node.core_node.type == core_pb2.NodeType.DEFAULT:
self.executable_nodes[node.core_node.name] = nid
def draw(self):
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=5)
self.top.columnconfigure(1, weight=1)
self.draw_command_frame()
self.draw_nodes_frame()
return
def draw_command_frame(self):
# the main frame
frame = ttk.Frame(self.top)
frame.grid(row=0, column=0, sticky="nsew")
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)
frame.rowconfigure(1, weight=1)
labeled_frame = ttk.LabelFrame(frame, text="Command line", padding=FRAME_PAD)
labeled_frame.grid(row=0, column=0, sticky="nsew", pady=PADY)
labeled_frame.rowconfigure(0, weight=1)
labeled_frame.columnconfigure(0, weight=1)
entry = ttk.Entry(labeled_frame, textvariable=self.cmd)
entry.grid(sticky="ew")
# results frame
labeled_frame = ttk.LabelFrame(frame, text="Command results", padding=FRAME_PAD)
labeled_frame.grid(row=1, column=0, sticky="nsew", pady=PADY)
labeled_frame.columnconfigure(0, weight=1)
labeled_frame.rowconfigure(0, weight=5)
labeled_frame.rowconfigure(1, weight=1)
self.result = CodeText(labeled_frame)
self.result.text.config(state=tk.DISABLED, height=15)
self.result.grid(sticky="nsew")
button_frame = ttk.Frame(labeled_frame, padding=FRAME_PAD)
button_frame.grid(sticky="nsew")
button_frame.columnconfigure(0, weight=1)
button_frame.columnconfigure(1, weight=1)
button = ttk.Button(button_frame, text="Run", command=self.click_run)
button.grid(sticky="nsew")
button = ttk.Button(button_frame, text="Close", command=self.destroy)
button.grid(row=0, column=1, sticky="nsew")
def draw_nodes_frame(self):
labeled_frame = ttk.LabelFrame(
self.top, text="Run on these nodes", padding=FRAME_PAD
)
labeled_frame.grid(row=0, column=1, sticky="nsew")
labeled_frame.columnconfigure(0, weight=1)
labeled_frame.rowconfigure(0, weight=5)
labeled_frame.rowconfigure(1, weight=1)
self.node_list = ListboxScroll(labeled_frame)
self.node_list.listbox.config(selectmode=tk.MULTIPLE)
self.node_list.grid(sticky="nsew")
for n in sorted(self.executable_nodes.keys()):
self.node_list.listbox.insert(tk.END, n)
button_frame = ttk.Frame(labeled_frame, padding=FRAME_PAD)
button_frame.grid(sticky="nsew")
button_frame.columnconfigure(0, weight=1)
button_frame.columnconfigure(1, weight=1)
button = ttk.Button(button_frame, text="All", command=self.click_all)
button.grid(sticky="nsew")
button = ttk.Button(button_frame, text="None", command=self.click_none)
button.grid(row=0, column=1, sticky="nsew")
def click_all(self):
self.node_list.listbox.selection_set(0, self.node_list.listbox.size() - 1)
def click_none(self):
self.node_list.listbox.selection_clear(0, self.node_list.listbox.size() - 1)
def click_run(self):
"""
run the command on each of the selected nodes and display the output to result text box
"""
command = self.cmd.get().strip()
self.result.text.config(state=tk.NORMAL)
self.result.text.delete("1.0", tk.END)
self.result.text.insert(
tk.END, f"> {command}\n" * len(self.node_list.listbox.curselection())
)
for selection in self.node_list.listbox.curselection():
node_name = self.node_list.listbox.get(selection)
node_id = self.executable_nodes[node_name]
response = self.app.core.client.node_command(
self.app.core.session_id, node_id, command
)
self.result.text.insert(
tk.END, f"> {node_name} > {command}:\n{response.output}\n"
)
self.result.text.config(state=tk.DISABLED)

View file

@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Callable
from core.api.grpc import core_pb2 from core.api.grpc import core_pb2
from core.gui.dialogs.customnodes import CustomNodesDialog from core.gui.dialogs.customnodes import CustomNodesDialog
from core.gui.dialogs.marker import MarkerDialog from core.gui.dialogs.marker import MarkerDialog
from core.gui.dialogs.runtool import RunToolDialog
from core.gui.graph.enums import GraphMode from core.gui.graph.enums import GraphMode
from core.gui.graph.shapeutils import ShapeType, is_marker from core.gui.graph.shapeutils import ShapeType, is_marker
from core.gui.images import ImageEnum, Images from core.gui.images import ImageEnum, Images
@ -485,6 +486,8 @@ class Toolbar(ttk.Frame):
def click_run_button(self): def click_run_button(self):
logging.debug("Click on RUN button") logging.debug("Click on RUN button")
dialog = RunToolDialog(self.app, self.app)
dialog.show()
def click_marker_button(self): def click_marker_button(self):
logging.debug("Click on marker button") logging.debug("Click on marker button")

View file

@ -89,7 +89,7 @@ Commands below can be used to run the core-daemon, the new core gui, and tests.
sudo python3 -m pipenv run core sudo python3 -m pipenv run core
# runs coretk gui # runs coretk gui
python3 -m pipenv run coretk python3 -m pipenv run core-pygui
# runs mocked unit tests # runs mocked unit tests
python3 -m pipenv run test-mock python3 -m pipenv run test-mock